Как аннотировать гистограмму значениями, отличными от get_height () - PullRequest
1 голос
/ 10 октября 2019

Я решил свой собственный вопрос после долгого и неудачного поиска, поэтому я публикую здесь вопрос и ответ сразу ниже.

Цель: построить проценты, но аннотировать необработанные значения. Проблема: вы можете аннотировать столбцы с вашими нанесенными на график данными (в моем случае, процентами), перебирая объект панели осей и вызывая get_height (), чтобы получить текст. Однако, если вы хотите аннотировать что-то еще, вам нужно одновременно выполнять итерацию по отдельным данным аннотации и вместо этого предоставлять их в виде текста аннотации. Мое первое решение не удалось, потому что отдельные данные аннотации, несмотря на то, что они были заказаны, были назначены столбцам совершенно не по порядку (я хотел бы, чтобы кто-нибудь мог мне сказать, почему):

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

Решение, которое я нашелзаключается в том, чтобы сжать объект панели осей и данные аннотации вместе, а затем выполнить итерацию по нему. Смотрите ответ ниже.

1 Ответ

1 голос
/ 10 октября 2019

Вот решение:

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)

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()
...