如何使用不同于 get_height() 的值注释条形图

How to annotate bar chart with values different to those from get_height()

经过漫长而失败的搜索后,我解决了自己的问题,所以我将问题和答案发布在这里。

目标:绘制百分比但注释原始计数。 问题:您可以通过遍历轴条对象并调用 get_height() 来获取文本,从而用绘制的数据(在我的例子中为百分比)对条进行注释。但是,如果您想注释其他内容,则需要同时遍历一些单独的注释数据并将其作为注释文本提供。我的第一个解决方案失败了,因为单独的注释数据尽管是有序的,但却完全乱序地分配给了条形图(如果有人能告诉我原因,我会很高兴):

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

label_freqs = {'Red': 8, 'Orange': 2, 'Yellow': 4, 'Green': 7, 'Blue': 1, 'Indigo': 6, 'Violet': 5}

df = pd.DataFrame(columns=('Colour', 'Frequency', 'Percentage'))
total = sum(label_freqs.values())
df['Colour'] = label_freqs.keys()
df['Frequency'] = [int(val) for val in label_freqs.values()]
df['Percentage'] = [round((int(val)/total)*100, ndigits=2) for val in label_freqs.values()]
df = df.sort_values(by='Frequency', ascending=False)

   Colour  Frequency  Percentage
0     Red          8       24.24
3   Green          7       21.21
5  Indigo          6       18.18
6  Violet          5       15.15
2  Yellow          4       12.12
1  Orange          2        6.06
4    Blue          1        3.03

def autolabel(my_bar, raw_freqs):
    """Attach a text label above each bar in *my_bar*, displaying its height."""
    i = 0
    for point in my_bar:
        height = point.get_height()
        ax.annotate('{}'.format(raw_freqs[i]),
                    xy=(point.get_x() + point.get_width() / 2, height),
                    xytext=(0, 3),  # 3 points vertical offset
                    textcoords="offset points",
                    ha='center', va='bottom', rotation=90)
        i += 1

我找到的解决方案是将轴条对象和注释数据压缩在一起,然后对其进行迭代。请参阅下面的答案。

解决方法如下:

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

fig, ax = plt.subplots()

plt.style.use('seaborn-darkgrid')
x_pos = np.arange(len(df))
ax_bar = ax.bar(x_pos, df['Percentage'], alpha=0.2)

ax.set_title('Colour Frequencies', fontsize=12, fontweight=0)
ax.set_xticks(x_pos)
ax.set_xticklabels(df['Colour'])
for tick in ax.get_xticklabels():
    tick.set_rotation(90)
ax.set_ylabel("Frequency in Percent")

def autolabel(my_bar, raw_freqs):
    """Attach a text label above each bar in *my_bar*, displaying its height."""
    for point, freq in zip(my_bar, raw_freqs):
        height = point.get_height()
        ax.annotate('{}'.format(freq),
                    xy=(point.get_x() + point.get_width() / 2, height),
                    xytext=(0, 3),  # 3 points vertical offset
                    textcoords="offset points",
                    ha='center', va='bottom', rotation=90)


autolabel(ax_bar, df['Frequency'])
plt.tight_layout()
plt.show()
plt.close()

  • matplotlib 3.4.2 开始,使用 matplotlib.pyplot.bar_label,并将 'Frequency' 列传递给 labels= 参数。
    • 请参阅此 answer 以获得详尽的解释和其他示例。
ax = df.plot(kind='bar', x='Colour', y='Percentage', rot=0, legend=False, xlabel='', alpha=0.2)
ax.set_title('Colour Frequencies', fontsize=12, fontweight=0)
ax.set_ylabel("Frequency in Percent")

ax.bar_label(ax.containers[0], labels=df.Frequency, rotation=90, padding=3)
plt.show()