Гистограмма в Seaborn

Я работаю с Seaborn и стараюсь, чтобы моя гистограмма выглядела лучше.

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

x = ['One', 'Two', 'Three', 'Four', 'Five']
y = [2, 3, 0, 4.5, 4]
y2 = [0, 0, -5, 0, 0]

sns.axes_style('white')
sns.set_style('white')

b = sns.barplot(x,y,color='pink')
sns.barplot(x,y2, color='red')

for p in b.patches:
    b.annotate(
        s='{:.1f}'.format(p.get_height()),
        xy=(p.get_x()+p.get_width()/2.,p.get_height()),
        ha='center',va='center',
        xytext=(0,10),
        textcoords='offset points'
)

b.set_yticks([])
sns.despine(ax=b, left=True, bottom=True)

введите здесь описание изображения

На самом деле я взял код для маркировки баров из другого потока при переполнении стека.

У меня проблема в том, что отрицательная полоса помечена на положительной стороне. Я также хочу избавиться от нулей в начале каждого графика и, возможно, переместить x = ['One','Two','Three','Four','Five'] в середину, где находятся нули, а не внизу.


person AK9309    schedule 11.09.2015    source источник
comment
Я думаю, ваша главная проблема в том, что вы дважды звоните в барплот. Поиск способа сжать его до одного вызова, вероятно, очень поможет. Кроме того, предоставьте ссылку на вопрос, который вы использовали для информирования этого сообщения.   -  person Paul H    schedule 11.09.2015
comment
Вы должны попытаться ограничить это только одним вопросом. На последний отвечу прямо сейчас: sns.despine(ax=b, bottom=True, left=True) избавится от рамки.   -  person Paul H    schedule 11.09.2015
comment
вы получаете 0.0, потому что вы перебираете все патчи, поэтому вам нужно включить условие, которое не аннотирует, когда значение p.get_height() не больше нуля.   -  person Paul H    schedule 11.09.2015
comment
Вероятно, гораздо проще просто добавить метки оси X и аннотации в виде текста с помощью ax.text(), чем бороться с аннотациями.   -  person iayork    schedule 11.09.2015
comment
вы должны оставить свой вопрос как есть - решение должно остаться в разделах ответов   -  person Paul H    schedule 11.09.2015
comment
Я не менял сам вопрос. Только что опубликовал решение, которое я придумал   -  person AK9309    schedule 11.09.2015
comment
правильно -- решения не входят в вопрос. они должны быть добавлены как еще один ответ.   -  person Paul H    schedule 11.09.2015
comment
Понятно. Спасибо. Я отредактировал вопрос обратно в исходную форму   -  person AK9309    schedule 11.09.2015


Ответы (3)


Вот логика, которая вам нужна, сделайте только 1 вызов barplot и поместите аннотацию на правильную сторону оси x.

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

x = ['One', 'Two', 'Three', 'Four', 'Five']
y = [2, 3, -5, 4.5, 4]

sns.axes_style('white')
sns.set_style('white')

colors = ['pink' if _y >=0 else 'red' for _y in y]
ax = sns.barplot(x, y, palette=colors)

for n, (label, _y) in enumerate(zip(x, y)):
    ax.annotate(
        s='{:.1f}'.format(abs(_y)),
        xy=(n, _y),
        ha='center',va='center',
        xytext=(0,10),
        textcoords='offset points',
        color=color,
        weight='bold'
    )

    ax.annotate(
        s=label,
        xy=(n, 0),
        ha='center',va='center',
        xytext=(0,10),
        textcoords='offset points',
    )  
# axes formatting
ax.set_yticks([])
ax.set_xticks([])
sns.despine(ax=ax, bottom=True, left=True)

введите здесь описание изображения

person Paul H    schedule 11.09.2015
comment
Нет необходимости вызывать barplot дважды; сразу за списком цветов, которые вы хотите использовать в качестве палитры. - person mwaskom; 11.09.2015
comment
Кроме того, для такого типа графика гораздо проще получить высоту столбца из объекта данных, чем из осей. - person mwaskom; 11.09.2015
comment
Ага. Удален дополнительный вызов, но выбрана установка цветов полос после построения графика. Я полагаю, что создание палитры на основе данных будет достаточно простым. Но так как мы все равно зацикливаемся на барах, возможно, оно того не стоит. - person Paul H; 11.09.2015
comment
@mwaskom просто пошел на это - person Paul H; 11.09.2015
comment
Спасибо. Это то, что я искал. Вы можете проверить мое решение. Поскольку я дважды просматриваю аннотацию, я могу аннотировать в разных позициях для отрицательных и положительных графиков. - person AK9309; 11.09.2015

Спасибо всем за комментарии. Вот мое решение: я переместил отрицательное число в конец списка. (Хотя особой разницы нет)

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

x = ['One', 'Two', 'Three', 'Four', 'Five']
y = [2, 3, 4, 4.5, 0]
y2 = [0, 0, 0, 0, -5]

figure()
sns.axes_style('white')
b = sns.barplot(x,y2, color='red')

for z in b.patches[4:5]:
    b.annotate(np.round(-z.get_height(),decimals=6),(z.get_x()+z.get_width()/2.,-z.get_height()),ha='center',va='center',xytext=(0,10),textcoords='offset points', color='w')   

b=sns.barplot(x,y, color='blue')
for p in b.patches[5:9]:
    b.annotate(np.round(p.get_height(),decimals=6),(p.get_x()+p.get_width()/2.,p.get_height()),ha='center',va='center',xytext=(0,-10),textcoords='offset points', color='w')
person AK9309    schedule 11.09.2015

К вашему сведению: окончательный ответ от AK9309 дает следующий график в моих настройках (python 2): Отображаемый график из кода AK9309

person CharlesG    schedule 11.02.2019