Matplotlib |应用对数刻度时绘图表示的变化

Matplotlib | Change in plot representation when applying logarithmic scale

给定一组要在 3D 图(如散点图)上表示的点,我认为由于 hist2d 和使用 [=12,以 2D 而不是 3D 绘制相同的数据会很有趣=].

此数据具有低值和高值(相差几个数量级),因此当表示为 hist2d 绘图时,一些数据为 "lost"(主要是较低的点)。

为了更好地了解所有值,我以对数刻度表示相同的图。结果,我注意到了两件不同的事情。首先,除了所表示的数据中包含的那些点之外,所有点都显示为白色像素(在对数尺度上看起来所有这些点都被忽略了)而不是作为最低点着色(另请参见色带的最低部分,它是白色而不是蓝色)。其次,也不是那么重要,色带中的比例值表示为 10 的幂。

所以我的问题涉及到这两点,所有 "white" 区域如何以蓝色表示,即最低点的颜色以及如何调整色带以不显示10 的幂,而不是正常表示数字 (1, 10, 100...)?

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


# Data
x = [8 for i in range(65)]
y = [75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11]
z = [895, 800, 710, 635, 565, 500, 440, 392, 347, 304, 268, 235, 205, 179, 156, 135, 117, 101, 89, 76, 64, 55, 47, 40, 34, 29, 25, 20, 16, 14, 12, 9, 7, 6, 5, 4, 3, 2.5, 2, 1.7, 1.3, 1, 0.775, 0.60, 0.45, 0.35, 0.25, 0.18, 0.14, 0.10, 0.07, 0.05, 0.035, 0.025, 0.020, 0.015, 0.010, 0.007, 0.006, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005]

fig = plt.figure()

# First plot
fig.add_subplot(211)

plt.hist2d(x, y, weights=z, bins=len(x), cmap='plasma')
cb = plt.colorbar(extend='both')
cb.set_label('height')

# Second plot. Using log scale
fig.add_subplot(212)

plt.hist2d(x, y, weights=z, bins=len(x), norm=mpl.colors.LogNorm(vmin=min(z), vmax=max(z)), cmap='plasma')
cb = plt.colorbar(extend='both')
cb.set_label('height')

plt.show()

(我假设所有的 x 值都是 8,以便创建一个最小的示例。)

白色"color"是因为零的对数为NaN或负无穷大,所以没有颜色(显示背景)。要将该背景颜色更改为 'plasma' 颜色图的 0 值:

plt.gca().set_facecolor(plt.get_cmap('plasma')(0))

为了避免使用科学记数法,并且只有大于 1 的刻度,您可以更改刻度和颜色条的刻度格式。

因为 z 的最小值是零,你在 0 和 1 之间失去了很多颜色 space。将 vmin 设置为 1(或 0.99)可以避免这种情况。

from matplotlib import ticker

fig.add_subplot(212)
plt.gca().set_facecolor(plt.get_cmap('plasma')(0))
plt.hist2d(x, y, weights=z, bins=len(x), norm=mpl.colors.LogNorm(vmin=1, vmax=max(z)), cmap='plasma')
cb = plt.colorbar(extend='both')
cb.set_label('height')
cb.set_ticks([1, 10, 100] + list(range(500, max(z), 500))) 
cb.ax.yaxis.set_major_formatter(ticker.ScalarFormatter()) # remove the scientific notation
cb.ax.yaxis.set_minor_locator(ticker.NullLocator()) # optionally remove the minor ticks