Python - 对数刻度的2D直方图 - 错误:`无法将float NaN转换为整数`

时间:2016-04-07 16:47:38

标签: python matplotlib plot histogram

这是我之前想要转换为二维直方图的情节。

enter image description here

mass_bh = (subhalos['SubhaloBHMass'] * 1e10 / 0.704) # in units of M_sol h^-1
vdisp = subhalos['SubhaloVelDisp']

nbins = 200
H, xedges, yedges = np.histogram2d(mass_bh,vdisp,bins=nbins)

fig2 = plt.figure()
plt.pcolormesh(xedges,yedges,Hmasked)
cbar = plt.colorbar()
cbar.ax.set_ylabel('g-r')

plt.ylabel(' $\log(\sigma)\quad$ [km s$^{-1}$] ')
plt.xlabel('$\log(M_{BH})\quad$ [M$_{\odot}$]')
plt.title('$M_{BH}-\sigma$ relation')

相反,给我这个

我之前的绘图将其xy值转换为对数缩放。但是对于这种直方图转换,它的效果并不是很好。

enter image description here

我该如何解决这个问题?

谢谢!

2 个答案:

答案 0 :(得分:2)

@armatita对数据的问题是正确的。我认为这完全取决于你如何在histogram2d内进行分箱。看看这个带有随机对数正态分布的例子是否有帮助。

import numpy as np
import matplotlib.pyplot as plt

n = 1000

x = np.logspace(2, 10, n)
y = x**1.5
y = y * np.random.lognormal(10, 3, n)

x_bins = np.logspace(np.log10(x.min()), np.log10(x.max()), np.sqrt(n))
y_bins = np.logspace(np.log10(y.min()), np.log10(y.max()), np.sqrt(n))
H, xedges, yedges = np.histogram2d(x, y, bins=[x_bins, y_bins])

fig = plt.figure()
ax1 = fig.add_subplot(211)
ax1.plot(x, y, 'o')
ax1.set_xscale('log')
ax1.set_yscale('log')

ax2 = fig.add_subplot(212)
ax2.pcolormesh(xedges, yedges, H.T)
ax2.set_xscale('log')
ax2.set_yscale('log')

我得到下面的图片,这是我相信你正在寻找的。另请注意H上的转置。 enter image description here

答案 1 :(得分:1)

只是建议你好奇心。虽然@lanery清楚地回答了这个问题,但我想分享一种在python中获得漂亮的2d直方图的不同方法。我不想使用通常产生相当难看的直方图的np.histogram2d,而是想回收py-sphviewer,这是一个使用自适应平滑内核渲染粒子模拟的python包。请考虑以下代码,该代码基于 lanery 的示例:

将numpy导入为np 将matplotlib.pyplot导入为plt 将sphviewer导入为sph

def myplot(x, y, extent=None, nb=8, xsize=500, ysize=500):   
    if(extent == None):
        xmin = np.min(x)
        xmax = np.max(x)
        ymin = np.min(y)
        ymax = np.max(y)
    else:
        xmin = extent[0]
        xmax = extent[1]
        ymin = extent[2]
        ymax = extent[3]

    k, = np.where( (x <= xmax) & (x >= xmin) & 
                   (y <= ymax) & (y >= ymin) )

    pos = np.zeros([3, len(k)])
    pos[0,:] = (x[k]-xmin)/(xmax-xmin)
    pos[1,:] = (y[k]-ymin)/(ymax-ymin)
    w = np.ones(len(k))

    P = sph.Particles(pos, w, nb=nb)
    S = sph.Scene(P)
    S.update_camera(r='infinity', x=0.5, y=0.5, z=0, 
                    extent=[-0.5,0.5,-0.5,0.5],
                    xsize=xsize, ysize=ysize)
    R = sph.Render(S)
    R.set_logscale()
    img = R.get_image()

    return img, [xmin,xmax,ymin,ymax]    


n = 1000

x = np.logspace(2, 10, n)
y = x**1.5
y = y * np.random.lognormal(10, 3, n)

H, xedges, yedges = np.histogram2d(x, y, bins=[np.logspace(np.log10(x.min()), np.log10(x.max())),
                                               np.logspace(np.log10(y.min()), np.log10(y.max()))])


img, extent = myplot(np.log10(x), np.log10(y))   #Call the function to make the 2d-histogram

fig = plt.figure()
ax1 = fig.add_subplot(311)
ax1.plot(x, y, 'o')
ax1.set_xscale('log')
ax1.set_yscale('log')

ax2 = fig.add_subplot(312)
ax2.pcolormesh(xedges, yedges, H.T)
ax2.set_xscale('log')
ax2.set_yscale('log')

ax3 = fig.add_subplot(313)
ax3.imshow(img, origin='lower', extent=extent, aspect='auto')

plt.show()

产生以下输出:

enter image description here

函数myplot()只是我编写的一个非常简单的函数,用于规范化数据并将其作为py-sphviewer的输入。平滑内核的长度通常由参数 nb 给出,该参数指定执行平滑的邻居的数量。虽然看起来很复杂,但是想法和实现都非常简单,与np.histogram2d相比,结果远远优于其他。但当然,这取决于您是否能够分发您的数据,以及为您的研究做这些的意义和后果。