【问题标题】:How to put a 'grid' (for example dividing the x-y plane into bins) on an image to calculate mean of the z-values in every bin and plot as a heatmap?如何在图像上放置“网格”(例如将 x-y 平面划分为 bin)以计算每个 bin 中 z 值的平均值并将其绘制为热图?
【发布时间】:2021-10-29 04:53:00
【问题描述】:

我的目标:

我有 x、y 和 z 值作为数组。例如:

x=np.array([10,2,-4,12,3,6,8,14])
y=np.array([5,5,-6,8,20,10,2,2])
z=np.array([4,6,10,40,22,14,20,8])

我想绘制一个热图,其中 z 值将作为每对 (x,y) 的强度或“权重”,轴将是 x 和 y 值。所以,我的情节将在 x-y 平面上。我想通过将我的 x-y 平面分成箱,然后计算每个箱内 z 值的平均值并将该平均值用作该箱的颜色或强度,在我的绘图顶部放置一个“网格”。我还想绘制另一个图,但我想将 z 值的方差绘制为箱内的强度。

我做了什么:

我按照以下方式对其进行了编码,但我认为我误解了一些东西。我认为我不太了解垃圾箱等(我是编程新手)。

import numpy as np
import matplotlib.pyplot as plt
x=np.array([10,2,-4,12,3,6,8,14])
y=np.array([5,5,-6,8,20,10,2,2])
z=np.array([4,6,10,40,22,14,-20,8])

# Bin the data onto a 2x2 grid
# Have to reverse x & y due to row-first indexing
zi, yi, xi = np.histogram2d(y, x, bins=(2,2), weights=z, normed=False)
counts, _, _ = np.histogram2d(y, x, bins=(2,2))

#to get mean divide by counts

zi = zi / counts
print(zi)

zi = np.ma.masked_invalid(zi)

fig, ax = plt.subplots()
sc=ax.pcolormesh(xi, yi, zi, edgecolors='black')
sct = ax.scatter(x, y, c=z, s=200) #shows the points in the bins 
fig.colorbar(sc)
ax.margins(0.05)

plt.show()

我被困在哪里:

我什至不确定上面的代码是否做对了。因此,请随意忘记它,并就解决此问题的任何其他标准方法向我提供建议。 使用上面的代码,我得到一个坐标轴限制由给定数据集自动确定的图,但我想将坐标轴保持在xmin=-20,xmax=20,ymin=-20,ymax=20。 此外,我不知道如何操纵箱内的 z 值来计算其他统计量,如方差或标准偏差等。

编辑:所以,我有一些更好的代码,它给出了 bin 中的平均 z 值,并使用np.histogram2d 进行绘图,我现在可以根据自己的喜好设置轴等,但使用它会给出 H 作为值的总和bins 和我可以从中得到平均值,但不能得到其他统计量,如方差。我想要一种对此进行编码的方法,以便我可以访问 bin 中的值,并且可以计算这些值的方差并将该结果用作热图的权重/强度。

我附上了 bin 中平均 z 的图。

import numpy as np
import matplotlib.pyplot as plt

x=np.array([10,2,4,12,3,6,8,14])
y=np.array([5,5,6,8,20,10,2,2])
z=np.array([4,6,10,40,22,14,20,8])

x_bins = np.linspace(0, 20, 3)
y_bins = np.linspace(0, 20, 3)

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])

print(H)
H1 = H/H_counts
print(H1)

plt.xlabel("x")
plt.ylabel("y")

plt.imshow(H1.T, origin='lower',  cmap='RdBu',
            extent=[xedges[0], xedges[-1], yedges[0], yedges[-1]])
plt.colorbar().set_label('mean z', rotation=270)

编辑 2:当我使用统计数据作为标准差时,我得到以下图表

右上角的深红色 bin 实际上是空的,没有 z 值,所以我希望标准偏差为“Nan”,而不是分配值 0。我该怎么做?

我的这个情节的代码是:

from scipy import stats
import numpy as np
import matplotlib.pyplot as plt

x=np.array([10,2,4,12,3,6,8,14])
y=np.array([5,5,6,8,20,10,2,2])
z=np.array([4,6,10,40,22,14,20,8])

x_bins = np.linspace(0, 20, 3)
y_bins = np.linspace(0, 20, 3)

H, xedges, yedges = np.histogram2d(x, y, bins = [x_bins, y_bins], weights = z)

#mean = stats.binned_statistic_2d(x,y,z,statistic='',bins=[x_bins,y_bins])
#mean.statistic
std = stats.binned_statistic_2d(x,y,z,statistic='std',bins=[x_bins,y_bins])
#std.statistic
#print(std.statistic)
plt.xlabel("x")
plt.ylabel("y")
plt.imshow(std.statistic.T, origin='lower',  cmap='RdBu',
            extent=[xedges[0], xedges[-1], yedges[0], yedges[-1]])
#plt.clim(0, 20)
plt.colorbar().set_label('std z', rotation=270)

【问题讨论】:

  • 也许是 seaborn 的sns.kdeplot(x=x,y=y,weights=z)
  • 嗨@JohanC,感谢您的建议,但我已经使用 stats.binned_statistic_2D 来解决它。我认为它适用于均值、中位数,但不适用于标准差。我在我的帖子的编辑 2 中提到了这个问题。出于某种原因,空箱显示 0 std 而不是 'Nan'...知道如何解决这个问题吗?我在我的 H 上尝试了 numpy.ma.masked_invalid 但它似乎没有帮助。谢谢:)
  • 欢迎来到 Stack Overflow。最后 2 个源栅栏似乎是重复的。您可以编辑帖子以删除一个吗?

标签: python arrays numpy matplotlib bin


【解决方案1】:

您的数据需要在常规网格上进行插值,因为您的计算机不知道哪个是没有值的 z 值。幸运的是,已经有一个功能:scipy.interpolate.griddata

import numpy as np
from scipy.interpolate import griddata
import matplotlib.pyplot as plt

# Dummy data
x=np.array([10,2,-4,12,3,6,8,14])
y=np.array([5,5,-6,8,20,10,2,2])
z=np.array([4,6,10,40,22,14,-20,8])

# Create a regular grid along x and y axis
grid_x, grid_y = np.mgrid[x.min():x.max()+1, y.min():y.max()+1]

# Linear interpolation
# But you could also use a cubic interpolation or whatever you want/need
z_interpolated = griddata((x,y), z, (grid_x, grid_y), method='linear')

# Plot the result:
plt.imshow(z_interpolated, cmap='plasma')

我们得到:

注意到图像边界上没有值,因为您的空间域未定义超出xy 中包含的值,因此使用线性插值,您的计算机无法猜测超出这些值的值点。因此,热图仅限于由您的点形成的凸包,其他任何内容都将是外推。

编辑:

如果您需要计算双向分箱统计,您可以使用:

scipy.stats.binned_statistic_2d()

如果我们想计算方差和均值:

from scipy import stats
std = stats.binned_statistic_2d(x,y,z,statistic='std',bins=[x_bins,y_bins])
mean = stats.binned_statistic_2d(x,y,z,statistic='mean',bins=[x_bins,y_bins])

其中mean 完全等同于您的H/H_counts

【讨论】:

  • 嗨@obchardon,谢谢,但我不认为这是我想要的...... y 轴应该从底部开始,而不是相反。另外,我希望每个 bin 中 z 值的平均值作为 bin 的强度,并且每个 bin 中 z 值的方差的另一个图是 bin 的强度。我已经编辑了我的帖子以包含更好的代码来获取平均值,但我需要一种方法来获得我不确定的方差。
  • 谢谢@obchardon!我将统计数据用于平均值和中位数,它可以工作,但是当我将它用于标准偏差时,为空的 bin 的标准差为 0,但我希望它用 Nan 填充(就像通常在平均值和中位数的情况下一样)。请检查我编辑的帖子。我怎么能这样做?
猜你喜欢
  • 2013-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-29
  • 2021-01-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多