Как выровнять каждый набор гистограмм по середине?Я пытаюсь создать диаграмму торнадо - PullRequest
0 голосов
/ 12 апреля 2019

Вопрос

Мой вопрос не имеет ничего общего с пакетом tornado .

Я хотел бы понять, есть ли способ создания диаграмм торнадо вPython - я предполагаю использовать matplotlib и seaborn, но подойдет любой другой пакет.

Краткое резюме таково: :

  • У меня есть набор гистограмм
  • скажем, у меня есть 3 переменные
  • для каждой из этих 3 переменных, я планирую влияние положительного изменения и отрицательного изменения
  • .положительные и отрицательные столбцы не выровнены;Мне нужно, чтобы они были выровнены по центру

Диаграмма торнадо - это набор гистограмм, центрированных по центру экрана;концепция очень проста:

  • у вас есть функция, которая вычисляет выходной сигнал на основе определенных входных данных
  • вы изменяете каждый из этих входных данных на определенный процент, скажем, + и -10%
  • вы рассчитываете, насколько сильно изменяется выходной сигнал
  • вы наносите на график результаты, ранжируя входные данные с наибольшим влиянием на тот, у которого наименьшее значение
  • , например, в (некрасиво) рисунок ниже, если цена увеличивается на 10%, выход (прибыль) увеличивается на величину красной полосы;если стоимость увеличивается на 10%, выход уменьшается на цифру красным

enter image description here

Что я сделал до сих пор

С кодом внизу я могу создать гистограмму с морским рожком;Я получаю одинаковый вывод с catplot и barplot;однако:

как я могу переместить полосу так, чтобы каждый набор оранжевых и синих полос был выровнен?

Это должно быть что-то вроде установки отрицательного интервала от одного барадругой, но я не могу передать аргумент ширины функциям seaborn, или я получаю

TypeError: barh() got multiple values for argument 'width'

Мой вывод:

enter image description here

Мой код:

**

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(style='darkgrid')

# creating a dataframe
df = pd.DataFrame()
df['input'] = ['x','y','z']
df['+']=[100,-50,10]
df['-']=[-80,60,-10]

#now stacking it
df2 = pd.melt(df, id_vars ='input', var_name='type of change', value_name='change in the output' )
print(df2)

fig,ax = plt.subplots(1,2)

sns.catplot(y='input', x='change in the output', hue='type of change',data=df2, kind='bar', \
            orient='h', ax = ax[0])

sns.barplot(y='input', x='change in the output', hue='type of change',data=df2, \
            orient='h', ax= ax[1], width =0.4)

РЕДАКТИРОВАТЬ: Комментарий указал этот matplotlib ответ.Я не был знаком с broken_barh, и я изучу его.Однако я не считаю свой вопрос точным дубликатом, потому что:

  • результат этого вопроса настолько уродлив, что его практически невозможно использовать, хотя мой не красив, но более полезен (по крайней мере, для моих целей).
  • превращение этого во что-то менее уродливое, вероятно, потребовало бы большой работы и означало бы отказ от удобства морского происхождения.

    Плюс, вы также можете видеть мой вопрос как другойвопросы, не связанные с диаграммой торнадо, поэтому у них есть (я осмелюсь думать) свои достоинства:

    • как передать аргумент ширины в seaborn?

    • как изменить выравнивание (интервал) стержней?

1 Ответ

1 голос
/ 12 апреля 2019

Это один из способов сделать это. Идея состоит в том, чтобы сначала разбить DataFrame, используя groupby, найти уникальные значения типов (+ и - в вашем случае), а затем нанести их на один общий объект оси ax. Для горизонтальной гистограммы необходимо указать аргумент height для управления шириной баров.

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(style='darkgrid')

# creating a dataframe
df = pd.DataFrame()
df['input'] = ['x','y','z']
df['+']=[100,-50,10]
df['-']=[-80,60,-10]

#now stacking it
df2 = pd.melt(df, id_vars ='input', var_name='type of change', value_name='change in the output' )

fig, ax = plt.subplots()
for typ, df in zip(df2['type of change'].unique(),df2.groupby('type of change')):
    ax.barh(df[1]['input'], df[1]['change in the output'], height=0.3, label=typ)
ax.legend(title = 'type of change')  

enter image description here

...