Аннотирование определенных c столбцов со значениями из Dataframe на Pandas столбчатых графиках - PullRequest
1 голос
/ 19 июня 2020

У меня есть столбиковая диаграмма:

enter image description here

, и это код, который я использую для его создания:

def performance_plot_builder(data: str, ax: pyplot.Axes):
    df = pandas.read_csv(data, header=0, sep=';')
    df[['library', 'function']] = df.name.str.split('_', expand=True, n=1)
    df = df.pivot('function', 'library', 'elapsed')

    normalized = df.div(df.max(axis=1), axis=0)
    normalized.plot(ax=ax, kind='bar', color=[c.value for c in Color])

    ax.set_ylabel('execution time (normalized)')

    for p in ax.patches:
        ax.annotate(str(p.get_height()), (p.get_x() * 1.005, p.get_height() * 1.005))

Данные сначала нормализуются относительно максимального значения между двумя сериями для каждого элемента, а затем наносятся на график. Мне удалось аннотировать значение на каждом столбце, однако я хотел бы несколько модификаций:

  1. Мне нужны только значения, отображаемые на максимуме каждого из двух значений. Например, для array_access будет отображаться только значение столбца stl, поскольку оно больше etl.

  2. Самое большое, что мне нужно, - это ненормализованные значения, которые будут отображаться вместо нормализованных значений, как сейчас (поэтому кадр данных df вместо кадра данных normalized.

  3. Я также хотел бы, чтобы метки были повернуты на 90 градусов, чтобы метки отображались на самих столбцах.

Это пример фрейма данных, который у меня есть:

library               etl           stl
function
copy         6.922975e-06  6.319098e-06
copy_if      1.369602e-04  1.423410e-04
count        6.135367e-05  1.179409e-04
count_if     1.332942e-04  1.908408e-04
equal        1.099963e-05  1.102448e-05
fill         5.337406e-05  9.352984e-05
fill_n       6.412923e-05  9.354095e-05
find         4.354274e-08  7.804437e-08
find_if      4.792641e-08  9.206846e-08
iter_swap    4.898631e-08  4.911048e-08
rotate       2.816952e-04  5.219732e-06
swap         2.832723e-04  2.882649e-04
swap_ranges  3.492764e-04  3.576686e-04
transform    9.739075e-05  1.080187e-04

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

Edit

Я был может в некоторой степени выполнить sh все модификации с помощью этого кода:

interleaved = [val for pair in zip(df['etl'], df['stl']) for val in pair]
for v, p in zip(interleaved, ax.patches):
    if p.get_height() == 1:
        ax.text(x=p.get_x() + 0.01, y=0.825, s=f'{v:.1E}', rotation=90, color='white')

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

1 Ответ

0 голосов
/ 21 июня 2020

Я смог разобраться:

size = len(ax.patches) // 2
for v_etl, v_stl, p_etl, p_stl in zip(df['etl'], df['stl'], ax.patches[:size], ax.patches[size:]):
    p, v = (p_etl, v_etl) if v_etl > v_stl else (p_stl, v_stl)
    ax.text(x=p.get_x() + 0.18 * p.get_width(), y=p.get_height() - 0.175, s=f'{v:.1E}', rotation=90, color='white')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...