我有 3 维分散数据 x、y、z。我想将 x 和 y 的箱中 z 的平均值绘制为十六进制图或二维直方图。有没有 matplotlib 函数可以做到这一点?尽管这似乎是一个常见问题,但我只能提出一些非常麻烦的实现。
例如这样的事情:
除了颜色应取决于 (x, y) bin 的平均 z 值(而不是默认 hexplot/2D 直方图功能中的 (x, y) bin 中的条目数)。
如果分箱是您所要求的,那么binned_statistic_2d可能适合您。这是一个例子:
from scipy.stats import binned_statistic_2d
import numpy as np
x = np.random.uniform(0, 10, 1000)
y = np.random.uniform(10, 20, 1000)
z = np.exp(-(x-3)**2/5 - (y-18)**2/5) + np.random.random(1000)
x_bins = np.linspace(0, 10, 10)
y_bins = np.linspace(10, 20, 10)
ret = binned_statistic_2d(x, y, z, statistic=np.mean, bins=[x_bins, y_bins])
fig, (ax0, ax1) = plt.subplots(1, 2, figsize=(12, 4))
ax0.scatter(x, y, c=z)
ax1.imshow(ret.statistic.T, origin='bottom', extent=(0, 10, 10, 20))
Run Code Online (Sandbox Code Playgroud)
@Andrea 的答案非常清晰且有帮助,但我想提一个不使用 scipy 库的更快的替代方案。
这个想法是做一个由 z 变量加权的 x 和 y 的二维直方图(它具有每个 bin 中 z 变量的总和),然后针对没有权重的直方图进行归一化(它具有每个 bin 中的计数数)。这样,您将计算每个 bin 中 z 变量的平均值。
代码:
import numpy as np
import matplotlib.pyplot as plt
x = np.random.uniform(0, 10, 10**7)
y = np.random.uniform(10, 20, 10**7)
z = np.exp(-(x-3)**2/5 - (y-18)**2/5) + np.random.random(10**7)
x_bins = np.linspace(0, 10, 50)
y_bins = np.linspace(10, 20, 50)
H, xedges, yedges = np.histogram2d(x, y, bins = [x_bins, y_bins], weights = z)
H_counts, xedges, yedges = np.histogram2d(x, y, bins = [x_bins, y_bins])
H = H/H_counts
plt.imshow(H.T, origin='lower', cmap='RdBu',
extent=[xedges[0], xedges[-1], yedges[0], yedges[-1]])
plt.colorbar()
Run Code Online (Sandbox Code Playgroud)
在我的计算机中,此方法比使用scipy 的binned_statistic_2d.