【问题标题】:Density map (heatmaps) in matplotlibmatplotlib 中的密度图(热图)
【发布时间】:2016-08-25 17:24:28
【问题描述】:

我有一个坐标列表:

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

【问题讨论】:

  • 请显示完整的错误堆栈跟踪;哪一行产生了错误?
  • 这个函数返回什么np.genfromtxt?它会返回一个元组吗?

标签: python matplotlib


【解决方案1】:

这有望让您走上正轨,但我绝对建议您阅读 pcolorpcolormesh 的文档。

您已评论# Plot the density map using nearest-neighbor interpolation,但由于Z 是一维数组,因此您没有任何用于密度图的二维密度数据。使用np.histogram2d 可以最轻松地创建密度图,我将在下面使用您的数据进行说明。

Z, xedges, yedges = np.histogram2d(x, y)

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

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

在获得与您发布的图像类似的图像之前,有一种方法可以解决,但它应该可以解释您的错误并帮助您走上正轨。

更新:获得更好、更平滑的密度图

假设您有两个一维数组,xy,您可以使用核密度估计通过以下方式获得更好的热图 [reference]

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 绘制高斯 KDE,具体取决于您所追求的效果/美学类型

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

我得到这张图片:

【讨论】:

  • 这样我得到这个错误:ValueError: cannot convert float NaN to integer
  • 这一定是您的csv 数据的问题。简单的nan 过滤可以使用x = x[numpy.isfinite(x)]y 完成。有关更多信息,请参阅此帖子:stackoverflow.com/questions/11620914/…
  • 是否可以有像我之前发布的热图这样的区域而不是矩形(由 histogram2d 创建)?
  • 一种常用的方法是使用核密度估计 (KDE)。抱歉假设,但我认为由于您在原始代码中导入了 gaussian_kde,因此平滑不是问题。给我一分钟更新我的答案。
  • 哦,我错过了。变坏。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-07
  • 2017-05-30
相关资源
最近更新 更多