带有对数轴的 matplotlib 条形图显示具有零值的条形标签
matplotlib bar chart with log axis showing labels for bars with zero values
我正在使用 Python 3.9.7
我有一些数据想绘制成条形图(下面的示例代码和图片)。
我想使用 对数 y 尺度绘制条形图。
然而,一些条形值可能为零,因此它们不会在对数刻度上显示为条形,但我仍然想显示 标签 每个柱,即使它是零。如果我线性绘制 y 轴,则会显示 0 标签,但不会显示对数标度。
有办法吗?
如果有其他绘图方式,我不会执着于 matplotlib。
谢谢。
import matplotlib.pyplot as plt
import numpy as np
month1 = [11, 1200, 0]
month2 = [55, 14, 37]
month3 = [111, 222, 300]
labels = ['a','b','c']
x_positions = np.arange(len(labels))
bar_width = 0.15
fig, ax = plt.subplots()
rects1 = ax.bar(x_positions - bar_width, month1, bar_width, label=labels[0])
rects2 = ax.bar(x_positions, month2, bar_width, label=labels[1])
rects3 = ax.bar(x_positions + bar_width, month3, bar_width, label=labels[2])
# Add some text for labels, title and custom x-axis tick labels, etc.
ax.set_ylabel('Count')
ax.set_xticks(x_positions, labels)
ax.set_yscale('log') # the 0 label will appear if I omit this line.
ax.legend()
ax.bar_label(rects1, padding=3)
ax.bar_label(rects2, padding=3)
ax.bar_label(rects3, padding=3)
fig.tight_layout()
plt.show()
未显示零柱标签,因为在此对数刻度上,0 无限远低于其他柱的顶部,因此从技术上讲看不到它。
您当然可以手动添加标签:
ax.text(x = x_positions[2] - bar_width,
y = ax.get_ylim()[0] + 1,
s = '0',
horizontalalignment='center')
+1
与其他标签的 padding=3
匹配。您可能需要为其他比例更改此设置。
这种方法可以通过遍历所有值来实现自动化,例如像这样(将另外两个 y 值设置为零以进行测试):
month1 = [11, 1200, 0]
month2 = [55, 0, 37]
month3 = [0, 222, 300]
labels = ['a', 'b', 'c']
x_positions = np.arange(len(labels))
bar_width = 0.15
y_min = 10
fig, ax = plt.subplots()
fig.tight_layout()
ax.set_yscale('log')
ax.set_ylim(y_min, 2000)
rects1 = ax.bar(x_positions - bar_width, month1, bar_width, label=labels[0])
rects2 = ax.bar(x_positions, month2, bar_width, label=labels[1])
rects3 = ax.bar(x_positions + bar_width, month3, bar_width, label=labels[2])
ax.set_ylabel('Count')
ax.set_xticks(x_positions, labels)
ax.legend()
ax.bar_label(rects1, padding=3)
ax.bar_label(rects2, padding=3)
ax.bar_label(rects3, padding=3)
for x, month in enumerate([month1, month2, month3]):
for x_offset, y in zip([-1, 0, 1], month):
if y < y_min:
ax.text(x = x + x_offset * bar_width,
y = y_min + 1,
s = str(y),
horizontalalignment='center')
我正在使用 Python 3.9.7
我有一些数据想绘制成条形图(下面的示例代码和图片)。
我想使用 对数 y 尺度绘制条形图。
然而,一些条形值可能为零,因此它们不会在对数刻度上显示为条形,但我仍然想显示 标签 每个柱,即使它是零。如果我线性绘制 y 轴,则会显示 0 标签,但不会显示对数标度。
有办法吗?
如果有其他绘图方式,我不会执着于 matplotlib。
谢谢。
import matplotlib.pyplot as plt
import numpy as np
month1 = [11, 1200, 0]
month2 = [55, 14, 37]
month3 = [111, 222, 300]
labels = ['a','b','c']
x_positions = np.arange(len(labels))
bar_width = 0.15
fig, ax = plt.subplots()
rects1 = ax.bar(x_positions - bar_width, month1, bar_width, label=labels[0])
rects2 = ax.bar(x_positions, month2, bar_width, label=labels[1])
rects3 = ax.bar(x_positions + bar_width, month3, bar_width, label=labels[2])
# Add some text for labels, title and custom x-axis tick labels, etc.
ax.set_ylabel('Count')
ax.set_xticks(x_positions, labels)
ax.set_yscale('log') # the 0 label will appear if I omit this line.
ax.legend()
ax.bar_label(rects1, padding=3)
ax.bar_label(rects2, padding=3)
ax.bar_label(rects3, padding=3)
fig.tight_layout()
plt.show()
未显示零柱标签,因为在此对数刻度上,0 无限远低于其他柱的顶部,因此从技术上讲看不到它。
您当然可以手动添加标签:
ax.text(x = x_positions[2] - bar_width,
y = ax.get_ylim()[0] + 1,
s = '0',
horizontalalignment='center')
+1
与其他标签的 padding=3
匹配。您可能需要为其他比例更改此设置。
这种方法可以通过遍历所有值来实现自动化,例如像这样(将另外两个 y 值设置为零以进行测试):
month1 = [11, 1200, 0]
month2 = [55, 0, 37]
month3 = [0, 222, 300]
labels = ['a', 'b', 'c']
x_positions = np.arange(len(labels))
bar_width = 0.15
y_min = 10
fig, ax = plt.subplots()
fig.tight_layout()
ax.set_yscale('log')
ax.set_ylim(y_min, 2000)
rects1 = ax.bar(x_positions - bar_width, month1, bar_width, label=labels[0])
rects2 = ax.bar(x_positions, month2, bar_width, label=labels[1])
rects3 = ax.bar(x_positions + bar_width, month3, bar_width, label=labels[2])
ax.set_ylabel('Count')
ax.set_xticks(x_positions, labels)
ax.legend()
ax.bar_label(rects1, padding=3)
ax.bar_label(rects2, padding=3)
ax.bar_label(rects3, padding=3)
for x, month in enumerate([month1, month2, month3]):
for x_offset, y in zip([-1, 0, 1], month):
if y < y_min:
ax.text(x = x + x_offset * bar_width,
y = y_min + 1,
s = str(y),
horizontalalignment='center')