这是我之前想要转换为二维直方图的情节。
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')
相反,给我这个
我之前的绘图将其x
和y
值转换为对数缩放。但是对于这种直方图转换,它的效果并不是很好。
我该如何解决这个问题?
谢谢!
答案 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')
答案 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()
产生以下输出:
函数myplot()只是我编写的一个非常简单的函数,用于规范化数据并将其作为py-sphviewer的输入。平滑内核的长度通常由参数 nb 给出,该参数指定执行平滑的邻居的数量。虽然看起来很复杂,但是想法和实现都非常简单,与np.histogram2d相比,结果远远优于其他。但当然,这取决于您是否能够分发您的数据,以及为您的研究做这些的意义和后果。