使用散点数据在MatPlotLib中生成热图

2024-03-29 12:41:49 发布

您现在位置:Python中文网/ 问答频道 /正文


Tags: python
3条回答

我不想使用np.hist2d,它通常会生成非常难看的直方图,而是希望循环使用py-sphviewer,这是一个python包,用于使用自适应平滑内核渲染粒子模拟,并且可以很容易地从pip安装(请参阅网页文档)。请考虑以下基于示例的代码:

import numpy as np
import numpy.random
import matplotlib.pyplot as plt
import sphviewer as sph

def myplot(x, y, nb=32, xsize=500, ysize=500):   
    xmin = np.min(x)
    xmax = np.max(x)
    ymin = np.min(y)
    ymax = np.max(y)

    x0 = (xmin+xmax)/2.
    y0 = (ymin+ymax)/2.

    pos = np.zeros([3, len(x)])
    pos[0,:] = x
    pos[1,:] = y
    w = np.ones(len(x))

    P = sph.Particles(pos, w, nb=nb)
    S = sph.Scene(P)
    S.update_camera(r='infinity', x=x0, y=y0, z=0, 
                    xsize=xsize, ysize=ysize)
    R = sph.Render(S)
    R.set_logscale()
    img = R.get_image()
    extent = R.get_extent()
    for i, j in zip(xrange(4), [x0,x0,y0,y0]):
        extent[i] += j
    print extent
    return img, extent

fig = plt.figure(1, figsize=(10,10))
ax1 = fig.add_subplot(221)
ax2 = fig.add_subplot(222)
ax3 = fig.add_subplot(223)
ax4 = fig.add_subplot(224)


# Generate some test data
x = np.random.randn(1000)
y = np.random.randn(1000)

#Plotting a regular scatter plot
ax1.plot(x,y,'k.', markersize=5)
ax1.set_xlim(-3,3)
ax1.set_ylim(-3,3)

heatmap_16, extent_16 = myplot(x,y, nb=16)
heatmap_32, extent_32 = myplot(x,y, nb=32)
heatmap_64, extent_64 = myplot(x,y, nb=64)

ax2.imshow(heatmap_16, extent=extent_16, origin='lower', aspect='auto')
ax2.set_title("Smoothing over 16 neighbors")

ax3.imshow(heatmap_32, extent=extent_32, origin='lower', aspect='auto')
ax3.set_title("Smoothing over 32 neighbors")

#Make the heatmap using a smoothing over 64 neighbors
ax4.imshow(heatmap_64, extent=extent_64, origin='lower', aspect='auto')
ax4.set_title("Smoothing over 64 neighbors")

plt.show()

生成以下图像:

enter image description here

如你所见,这些图像看起来非常漂亮,我们能够识别出它的不同子结构。这些图像是为特定区域内的每个点扩展给定的权重而构建的,该权重由平滑长度定义,而平滑长度又由到更接近的nb邻居的距离来确定(我选择了16、32和64作为示例)。因此,与低密度区域相比,高密度区域通常分布在较小的区域上。

函数myplot只是一个非常简单的函数,我编写这个函数是为了将x,y数据交给py sphviewer来完成这个魔术。

如果不需要六边形,可以使用numpy的histogram2d函数:

import numpy as np
import numpy.random
import matplotlib.pyplot as plt

# Generate some test data
x = np.random.randn(8873)
y = np.random.randn(8873)

heatmap, xedges, yedges = np.histogram2d(x, y, bins=50)
extent = [xedges[0], xedges[-1], yedges[0], yedges[-1]]

plt.clf()
plt.imshow(heatmap.T, extent=extent, origin='lower')
plt.show()

这是一个50x50热图。如果需要,比如512x384,可以将bins=(512, 384)放入对histogram2d的调用中。

示例:Matplotlib heat map example

Matplotlib字典中,我想您需要一个hexbin绘图。

如果您不熟悉这种类型的绘图,它只是一个二元直方图其中xy平面由规则的六边形网格细分。

所以从柱状图上,你可以计算每个六边形中的点数,将绘图区域离散化为一组窗口,将每个点分配给其中一个窗口;最后,将窗口映射到一个颜色数组,得到一个hexbin图。

尽管不像圆或正方形那样常用,但六边形是装箱容器几何结构的更好选择,这是直观的:

  • 六边形具有近邻对称性, e、 从正方形边界上的一点到另一点的距离 在这个正方形内,并非所有地方都相等)和

  • 六边形是最高的n多边形,它给出正平面 镶嵌(即,您可以使用六边形瓷砖安全地重新建模厨房地板,因为完成后瓷砖之间不会有任何空隙——对于所有其他更高的n,n>;=7,多边形来说不是这样)。

Matplotlib使用术语hexbinplot;对于R的所有{a1}也是(AFAIK);我仍然不知道这是否是这类图的普遍接受的术语,尽管我怀疑可能是因为hexbin六角形binning的缩写,这描述了准备显示数据的基本步骤。)


from matplotlib import pyplot as PLT
from matplotlib import cm as CM
from matplotlib import mlab as ML
import numpy as NP

n = 1e5
x = y = NP.linspace(-5, 5, 100)
X, Y = NP.meshgrid(x, y)
Z1 = ML.bivariate_normal(X, Y, 2, 2, 0, 0)
Z2 = ML.bivariate_normal(X, Y, 4, 1, 1, 1)
ZD = Z2 - Z1
x = X.ravel()
y = Y.ravel()
z = ZD.ravel()
gridsize=30
PLT.subplot(111)

# if 'bins=None', then color of each hexagon corresponds directly to its count
# 'C' is optional--it maps values to x-y coordinates; if 'C' is None (default) then 
# the result is a pure 2D histogram 

PLT.hexbin(x, y, C=z, gridsize=gridsize, cmap=CM.jet, bins=None)
PLT.axis([x.min(), x.max(), y.min(), y.max()])

cb = PLT.colorbar()
cb.set_label('mean value')
PLT.show()   

enter image description here

相关问题 更多 >