密度图(热力图)在matplotlib中的应用

11

我有一个坐标列表:

y,x
445.92,483.156
78.273,321.512
417.311,204.304
62.047,235.216
87.24,532.1
150.863,378.184
79.981,474.14
258.894,87.74
56.496,222.336
85.105,454.176
80.408,411.672
90.656,433.568
378.027,441.296
433.964,290.6
453.606,317.648
383.578,115.432
128.232,312.496
116.276,93.536
94.072,222.336
52.226,327.308
321.663,187.56
392.972,279.008

我想使用matplotlib基于这些点绘制一个密度地图(或热力图)。我正在使用pcolormesh和contourf。问题在于pcolormesh的间距大小不同:

这里输入图片描述

这是代码:

x, y = np.genfromtxt('pogba_t1314.csv', delimiter=',', unpack=True)

#print(x[1], y[1])
y = y[np.logical_not(np.isnan(y))]
x = x[np.logical_not(np.isnan(x))]
k = gaussian_kde(np.vstack([x, y]))
xi, yi = np.mgrid[x.min():x.max():x.size**0.5*1j,y.min():y.max():y.size**0.5*1j]
zi = k(np.vstack([xi.flatten(), yi.flatten()]))

fig = plt.figure(figsize=(9,10))
ax1 = fig.add_subplot(211)


ax1.pcolormesh(xi, yi, zi.reshape(xi.shape), alpha=0.5)

ax1.plot(y,x, "o")
ax1.set_xlim(0, 740)
ax1.set_ylim(515, 0)

#overlay soccer field
im = plt.imread('statszone_football_pitch.png')
ax1.imshow(im, extent=[0, 740, 0, 515], aspect='auto')


fig.savefig('pogba1516.png')

这是一个csv文件的链接: https://dl.dropboxusercontent.com/u/12348226/pogba_t1314.csv


请展示完整的错误堆栈跟踪;哪一行代码产生了错误? - Cyb3rFly3r
这个函数 np.genfromtxt 返回什么?它返回一个元组吗? - AKS
1个回答

23
希望这能帮助你找到正确的方向,但我强烈建议阅读pcolorpcolormesh的文档。您已经评论了 # Plot the density map using nearest-neighbor interpolation,但是由于Z是一个一维数组,因此您没有任何2D密度数据用于创建密度图。如下所示,使用您的数据可以最轻松地通过使用np.histogram2d 来创建密度图。
Z, xedges, yedges = np.histogram2d(x, y)

Z现在是一个包含你的x,y坐标分布信息的二维数组。可以用pcolormesh来绘制这个分布,就像这样:

plt.pcolormesh(xedges, yedges, Z.T)

离你发布的那张图片还有很长的一段路要走,但这个过程可以解释你的错误并帮助你找到正确的方向。

更新:更加流畅的密度图

假设你有两个一维数组 xy,你可以使用核密度估计来获取更好的热力图,方法如下 [参考文献]

from scipy.stats.kde import gaussian_kde

k = gaussian_kde(np.vstack([x, y]))
xi, yi = np.mgrid[x.min():x.max():x.size**0.5*1j,y.min():y.max():y.size**0.5*1j]
zi = k(np.vstack([xi.flatten(), yi.flatten()]))

现在你可以使用pcolormeshcontourf来绘制高斯核密度估计图,具体取决于你想要的效果/美学。

import matplotlib.pyplot as plt

fig = plt.figure(figsize=(7,8))
ax1 = fig.add_subplot(211)
ax2 = fig.add_subplot(212)

# alpha=0.5 will make the plots semitransparent
ax1.pcolormesh(xi, yi, zi.reshape(xi.shape), alpha=0.5)
ax2.contourf(xi, yi, zi.reshape(xi.shape), alpha=0.5)

ax1.set_xlim(x.min(), x.max())
ax1.set_ylim(y.min(), y.max())
ax2.set_xlim(x.min(), x.max())
ax2.set_ylim(y.min(), y.max())

# you can also overlay your soccer field
im = plt.imread('soccerPitch.jpg')
ax1.imshow(im, extent=[x.min(), x.max(), y.min(), y.max()], aspect='auto')
ax2.imshow(im, extent=[x.min(), x.max(), y.min(), y.max()], aspect='auto')

我看到这张图片:

在这里输入图像描述


该图片显示了一个网站的界面,用户可以输入用户名和密码来登录。

这一定是你的 csv 数据有问题。可以使用 x = x[numpy.isfinite(x)] 和同样的方法处理 y 来进行简单的 nan 过滤。更多信息请参见此帖子:https://dev59.com/zmgu5IYBdhLWcg3wDS0G - lanery
是否可以像我之前发布的热力图一样,而不是直方图二维数组创建的矩形,来创建区域? - slash89mf
一种常见的方法是使用核密度估计(KDE)。抱歉先假设了一下,但我认为既然您在原始代码中导入了gaussian_kde,平滑不是问题。请给我一分钟更新我的答案。 - lanery
抱歉,刚才出了点问题。现在应该没问题了(将“bins”替换为“x.size0.5”和“y.size0.5”)。 - lanery
1
哦,我错过了。很糟糕。谢谢! - slash89mf
显示剩余10条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接