简体   繁体   English

Python-2D直方图以对数比例绘制—错误:无法将float NaN转换为整数

[英]Python - 2D Histogram plot in log scale — Error: `cannot convert float NaN to integer`

This is my previous plot that i want to convert to 2-d histogram. 这是我以前的图,我想转换为二维直方图。

在此处输入图片说明

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

This instead, gives me this 相反,这给了我

My previous plot has both its x and y values converted to logarithmic scaling. 我以前的绘图将xy值都转换为对数比例。 But for this histogram conversion, it's not working out so great. 但是对于这种直方图转换,效果不是很好。

在此处输入图片说明

How can I work around this? 我该如何解决?

Thank you! 谢谢!

@armatita is right about the problem being the data. @armatita认为问题在于数据是正确的。 I think it all comes down to how you do your binning inside histogram2d . 我认为一切都取决于您如何在histogram2d进行装箱。 See if this example with a random lognormal distribution helps. 看看这个具有随机对数正态分布的示例是否有帮助。

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

I get the below image, which is what I believe you are looking for. 我得到以下图像,这是我相信您正在寻找的图像。 Also note the transpose on H . 还要注意在H上的转置。 在此处输入图片说明

Just a suggestion to pick up your curiosity. 只是一个建议,可以激发您的好奇心。 Although @lanery clearly answers the question, I would like to share a different method of getting a nice 2d histogram in python. 尽管@lanery清楚地回答了这个问题,但我想分享另一种在python中获得漂亮的2d直方图的方法。 Instead of using np.histogram2d, which in general produces quite ugly histograms, I would like to recycle py-sphviewer , a python package for rendering particle simulations using an adaptive smoothing kernel. 我不想使用np.histogram2d(通常会产生非常难看的直方图),而是要回收py-sphviewer ,这是一个使用自适应平滑内核渲染粒子模拟的python包。 Consider the following code, which is based on the example of lanery : 考虑以下代码,该代码基于lanery的示例:

import numpy as np import matplotlib.pyplot as plt import sphviewer as sph 导入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()

which produces the following output: 产生以下输出:

在此处输入图片说明

The function myplot() is just a very simple function that I've written in order to normalize the data and give it as input of py-sphviewer. 函数myplot()只是我编写的一个非常简单的函数,用于规范化数据并将其作为py-sphviewer的输入。 The length of the smoothing kernel is typically given by the parameter nb , which specify the number of neighbours over which the smoothing is performed. 平滑内核的长度通常由参数nb给出,该参数指定要在其上进行平滑的邻居数。 Although is seems complicated at first sight, the ideas and the implementation are very easy, and the result is by far superior compared to np.histogram2d. 尽管乍看之下似乎很复杂,但是其思想和实现非常简单,与np.histogram2d相比,结果要好得多。 But of course, it depends whether you are able to spread out your data or not, and what the meaning and consequence of doing that for your research. 但是,当然,这取决于您是否能够分发数据,以及这样做对研究的意义和后果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM