如何正确生成三维直方图

7 投票
4 回答
29518 浏览
提问于 2025-04-17 08:00

这是一个关于在Python中创建三维直方图的一般性问题。

我尝试使用以下代码中的X和Y数组来创建一个三维直方图。

import matplotlib
import pylab
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.axes3d import Axes3D
from matplotlib import cm

def threedhist():
    X = [1, 3, 5, 8, 6, 7, 1, 2, 4, 5]
    Y = [3, 4, 3, 6, 5, 3, 1, 2, 3, 8]
    fig = pylab.figure()
    ax = Axes3D(fig)
    ax.hist([X, Y], bins=10, range=[[0, 10], [0, 10]])
    plt.xlabel('X')
    plt.ylabel('Y')
    plt.zlabel('Frequency')
    plt.title('Histogram')
    plt.show()

但是,我遇到了以下错误。

Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    a3dhistogram()
  File "C:/Users/ckiser/Desktop/Projects/Tom/Python Files/threedhistogram.py", line 24, in a3dhistogram
    ax.hist([X, Y], bins=10, range=[[0, 10], [0, 10]])
  File "C:\Python27\lib\site-packages\matplotlib\axes.py", line 7668, in hist
    m, bins = np.histogram(x[i], bins, weights=w[i], **hist_kwargs)
  File "C:\Python27\lib\site-packages\numpy\lib\function_base.py", line 169, in histogram
    mn, mx = [mi+0.0 for mi in range]
TypeError: can only concatenate list (not "float") to list

我试过在这一行中加上和不加上“[”来运行代码:
ax.hist([X, Y], bins=10, range=[[0, 10], [0, 10]])
我也尝试过用numpy的函数,但也没有成功:
H, xedges, yedges = np.histogram2d(x, y, bins = (10, 10))
我是不是漏掉了什么步骤或者参数?任何建议都非常感谢。

4 个回答

1

在这个回答中,提供了一个关于如何绘制散点的二维和三维直方图的解决方案。使用起来很简单:

points, sub = hist2d_scatter( radius, density, bins=4 )

points, sub = hist3d_scatter( temperature, density, radius, bins=4 )

这里的 sub 是一个 matplotlib"Subplot" 实例(可以是三维的,也可以不是),而 points 则包含了用于散点图的点。

3

你可以看看这个链接:https://matplotlib.org/stable/gallery/mplot3d/hist3d.html,里面有一个可以运行的示例代码。

我对那个链接里的代码做了一些改进,让它更像一个直方图:

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
x = [1, 3, 5, 8, 6, 7, 1, 2, 4, 5]
y = [3, 4, 3, 6, 5, 3, 1, 2, 3, 8]

hist, xedges, yedges = np.histogram2d(x, y, bins=(4,4))
xpos, ypos = np.meshgrid(xedges[:-1]+xedges[1:], yedges[:-1]+yedges[1:])

xpos = xpos.flatten()/2.
ypos = ypos.flatten()/2.
zpos = np.zeros_like (xpos)

dx = xedges [1] - xedges [0]
dy = yedges [1] - yedges [0]
dz = hist.flatten()

ax.bar3d(xpos, ypos, zpos, dx, dy, dz, color='b', zsort='average')
plt.xlabel ("X")
plt.ylabel ("Y")

plt.show()

我不太确定怎么用 Axes3D.hist() 来实现。

13

我在一个关于彩色3D柱状图的相关讨论中发过这个,但我觉得在这里也很相关,因为我在任何一个讨论中都找不到我需要的完整答案。这段代码可以生成一个直方图散点图,适用于任何类型的x-y数据。图的高度表示这个区间内值的频率。举个例子,如果你有很多数据点的坐标是(x,y) = (20,20),那么这个柱子就会很高,而且是红色的。如果在(x,y) = (100,100)这个区间的数据点很少,那么这个柱子就会很低,而且是蓝色的。

注意:结果会根据你有多少数据和你为直方图选择了多少个区间而有很大不同。记得根据情况调整哦!

xAmplitudes = #your data here
yAmplitudes = #your other data here

x = np.array(xAmplitudes)   #turn x,y data into numpy arrays
y = np.array(yAmplitudes)

fig = plt.figure()          #create a canvas, tell matplotlib it's 3d
ax = fig.add_subplot(111, projection='3d')

#make histogram stuff - set bins - I choose 20x20 because I have a lot of data
hist, xedges, yedges = np.histogram2d(x, y, bins=(20,20))
xpos, ypos = np.meshgrid(xedges[:-1]+xedges[1:], yedges[:-1]+yedges[1:])

xpos = xpos.flatten()/2.
ypos = ypos.flatten()/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()

下面是我大约75,000个数据点的结果。注意,你可以拖动和放置以查看不同的角度,可能还想保存多个视图以备展示或留念。

3d histogram side view 3d histogram perspective 2

撰写回答