如何在 matplotlib 极坐标 2D 直方图中创建曲线箱?

How do I create curved bins in matplotlib polar 2D histogram?

我正在使用 matplotlib 和以下代码(改编自 )在 Python 3.7 中绘制极坐标 2d 直方图:

import numpy as np
import matplotlib.pyplot as plt

# input data
azimut = np.random.rand(3000)*2*np.pi
radius = np.random.rayleigh(9, size=3000)

# binning
rbins = np.linspace(0, radius.max(), 10)
abins = np.linspace(0, 2*np.pi, 10)

# histogram
hist, _, _ = np.histogram2d(azimut, radius, bins=(abins, rbins))
A, R = np.meshgrid(abins, rbins)

# plot
fig, ax = plt.subplots(subplot_kw=dict(projection="polar"))

pc = ax.pcolormesh(A, R, hist.T, cmap='inferno')
fig.colorbar(pc)

plt.show()

产生以下情节:

由于 bin 尺寸较大,极投影看起来更像多边形而不是圆形。

有什么办法可以绘制出这个图,使 bin 看起来是弯曲的而不是直的? IE。这样无论 bin 大小如何,绘图始终是圆形的,并且当 bin 较大时不会变成多边形?

最好使用 matplotlib 解决方案,但也欢迎其他解决方案。

非常感谢您的帮助。

为了获得圆润的外观,可以将网格细分为更多的角度。请注意,np.linspace(0, 2 * np.pi, 10) 创建了 9 个 bin(和 10 个边界)。对于细分网格,您需要例如90 个箱子,所以 91 个边界。直方图值需要按相同的因子重复。

以下代码使用不同的颜色图进行调试。可选网格突出显示原始边界。

import numpy as np
import matplotlib.pyplot as plt

# input data
azimut = np.random.rand(3000) * 2 * np.pi
radius = np.random.rayleigh(9, size=3000)

# binning
rbins = np.linspace(0, radius.max(), 7)
abins = np.linspace(0, 2 * np.pi, 10)
subdivs = 10
abins2 = np.linspace(0, 2 * np.pi, (len(abins) - 1) * subdivs + 1)

# histogram
hist, _, _ = np.histogram2d(azimut, radius, bins=(abins, rbins))
A1, R1 = np.meshgrid(abins, rbins)
A2, R2 = np.meshgrid(abins2, rbins)

fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(10, 4), subplot_kw=dict(projection="polar"))

# plot with original mesh
pc1 = ax1.pcolormesh(A1, R1, hist.T, cmap='hsv')
ax1.tick_params(axis='y', labelcolor='white')
ax1.set_xticks(abins[:-1])
fig.colorbar(pc1, ax=ax1)

# plot with subdivided mesh
pc2 = ax2.pcolormesh(A2, R2, np.repeat(hist.T, subdivs, axis=1), cmap='hsv')
ax2.tick_params(axis='y', labelcolor='white')
ax2.set_xticks(abins[:-1])
ax2.set_yticks(rbins, minor=True)
ax2.grid(axis='x', color='white')
ax2.grid(axis='y', which='minor', color='white')
fig.colorbar(pc2, ax=ax2)

plt.tight_layout()
plt.show()