绘制 3D 条形直方图

问题描述 投票:0回答:3
我有一些 x 和 y 数据,我想用它们生成带有颜色渐变(bwr 或其他)的 3D 直方图。

我编写了一个脚本,绘制了 x 和 y 脓肿的有趣值,介于 -2 和 2 之间:

import numpy as np import numpy.random import matplotlib.pyplot as plt # To generate some test data x = np.random.randn(500) y = np.random.randn(500) XY = np.stack((x,y),axis=-1) def selection(XY, limitXY=[[-2,+2],[-2,+2]]): XY_select = [] for elt in XY: if elt[0] > limitXY[0][0] and elt[0] < limitXY[0][1] and elt[1] > limitXY[1][0] and elt[1] < limitXY[1][1]: XY_select.append(elt) return np.array(XY_select) XY_select = selection(XY, limitXY=[[-2,+2],[-2,+2]]) heatmap, xedges, yedges = np.histogram2d(XY_select[:,0], XY_select[:,1], bins = 7, range = [[-2,2],[-2,2]]) extent = [xedges[0], xedges[-1], yedges[0], yedges[-1]] plt.figure("Histogram") #plt.clf() plt.imshow(heatmap.T, extent=extent, origin='lower') plt.show()

并给出正确的结果:

现在,我想将其转换为 3D 直方图。不幸的是,我没有成功地用

bar3d

 正确绘制它,因为默认情况下它采用 x 和 y 的长度作为横坐标。 

我非常确定有一种非常简单的方法可以使用 imshow 以 3D 形式绘制此图。就像一个未知的选项...

python matplotlib histogram matplotlib-3d
3个回答
13
投票
我终于成功了。我几乎肯定有更好的方法来做到这一点,但至少它有效:

import numpy as np import numpy.random import matplotlib.pyplot as plt # To generate some test data x = np.random.randn(500) y = np.random.randn(500) XY = np.stack((x,y),axis=-1) def selection(XY, limitXY=[[-2,+2],[-2,+2]]): XY_select = [] for elt in XY: if elt[0] > limitXY[0][0] and elt[0] < limitXY[0][1] and elt[1] > limitXY[1][0] and elt[1] < limitXY[1][1]: XY_select.append(elt) return np.array(XY_select) XY_select = selection(XY, limitXY=[[-2,+2],[-2,+2]]) xAmplitudes = np.array(XY_select)[:,0]#your data here yAmplitudes = np.array(XY_select)[:,1]#your other data here fig = plt.figure() #create a canvas, tell matplotlib it's 3d ax = fig.add_subplot(111, projection='3d') hist, xedges, yedges = np.histogram2d(x, y, bins=(7,7), range = [[-2,+2],[-2,+2]]) # you can change your bins, and the range on which to take data # hist is a 7X7 matrix, with the populations for each of the subspace parts. xpos, ypos = np.meshgrid(xedges[:-1]+xedges[1:], yedges[:-1]+yedges[1:]) -(xedges[1]-xedges[0]) xpos = xpos.flatten()*1./2 ypos = ypos.flatten()*1./2 zpos = np.zeros_like (xpos) dx = xedges [1] - xedges [0] dy = yedges [1] - yedges [0] dz = hist.flatten() cmap = cm.get_cmap('jet') # Get desired colormap - you can change this! max_height = np.max(dz) # get range of colorbars so we can normalize min_height = np.min(dz) # scale each z to [0,1], and get their rgb values rgba = [cmap((k-min_height)/max_height) for k in dz] ax.bar3d(xpos, ypos, zpos, dx, dy, dz, color=rgba, zsort='average') plt.title("X vs. Y Amplitudes for ____ Data") plt.xlabel("My X data source") plt.ylabel("My Y data source") plt.savefig("Your_title_goes_here") plt.show()

我使用这个

示例,但我修改了它,因为它引入了偏移量。结果是这样的:


5
投票
您可以使用如下简单的方法生成相同的结果:

import numpy as np import matplotlib.pyplot as plt x = np.linspace(-2, 2, 7) y = np.linspace(-2, 2, 7) xx, yy = np.meshgrid(x, y) z = xx*0+yy*0+ np.random.random(size=[7,7]) plt.imshow(z, interpolation='nearest', cmap=plt.cm.viridis, extent=[-2,2,2,2]) plt.show() from mpl_toolkits.mplot3d import Axes3D ax = Axes3D(plt.figure()) ax.plot_surface(xx, yy, z, cmap=plt.cm.viridis, cstride=1, rstride=1) plt.show()

结果如下:


0
投票
这篇文章中接受的答案很好,但有一个错误。应进行以下修复之一。否则,数据看起来是镜像的。

dz = np.transpose(hist).flatten()

ypos, xpos = np.meshgrid(yedges[:-1] + yedges[1:], xedges[:-1] + xedges[1:])

当你展平 np.histogram2d 的输出时,你会得到每个 x 堆叠在一起的一整行 y 值。 然后展平 meshgrid 的输出,得到沿数组堆叠的递增 x 和固定 y。因此,两者不再匹配

© www.soinside.com 2019 - 2024. All rights reserved.