Seaborn Catplot устанавливает значения над полосами

Я нарисовал catplot в seaborn вот так

import seaborn as sns
import pandas as pd

data  = {'year': [2016, 2013, 2014, 2015, 2016, 2013, 2014, 2015, 2016, 2013, 2014, 2015, 2016, 2013, 2014, 2015, 2016, 2013, 2014, 2015], 'geo_name': ['Michigan', 'Michigan', 'Michigan', 'Michigan', 'Washtenaw County, MI', 'Washtenaw County, MI', 'Washtenaw County, MI', 'Washtenaw County, MI', 'Ann Arbor, MI', 'Ann Arbor, MI', 'Ann Arbor, MI', 'Ann Arbor, MI', 'Philadelphia, PA', 'Philadelphia, PA', 'Philadelphia, PA', 'Philadelphia, PA', 'Ann Arbor, MI Metro Area', 'Ann Arbor, MI Metro Area', 'Ann Arbor, MI Metro Area', 'Ann Arbor, MI Metro Area'], 'geo': ['04000US26', '04000US26', '04000US26', '04000US26', '05000US26161', '05000US26161', '05000US26161', '05000US26161', '16000US2603000', '16000US2603000', '16000US2603000', '16000US2603000', '16000US4260000', '16000US4260000', '16000US4260000', '16000US4260000', '31000US11460', '31000US11460', '31000US11460', '31000US11460'], 'income': [50803.0, 48411.0, 49087.0, 49576.0, 62484.0, 59055.0, 60805.0, 61003.0, 57697.0, 55003.0, 56835.0, 55990.0, 39770.0, 37192.0, 37460.0, 38253.0, 62484.0, 59055.0, 60805.0, 61003.0], 'income_moe': [162.0, 163.0, 192.0, 186.0, 984.0, 985.0, 958.0, 901.0, 2046.0, 1688.0, 1320.0, 1259.0, 567.0, 424.0, 430.0, 511.0, 984.0, 985.0, 958.0, 901.0]}
df = pd.DataFrame(data)

g = sns.catplot(x='year', y='income', data=df, kind='bar', hue='geo_name', legend=True)
g.fig.set_size_inches(15,8)
g.fig.subplots_adjust(top=0.81,right=0.86)  

Я получаю вывод, как показано ниже

Seaborn Catplot устанавливает значения над полосами

Я хочу добавить значения каждой полосы вверху в представлении K. Например в 2013 полоса для Michigan находится на 48411, поэтому я хочу добавить значение 48.4K поверх этой полосы. Аналогично для всех баров.

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
10
0
7 705
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Это грубое решение, но оно помогает.

Мы добавляем текст к объекту axes, созданному сюжетом.

Позиция Y проста, так как она точно соответствует значению данных. Мы можем просто добавить 500 к каждому значению, чтобы метка хорошо располагалась в верхней части столбца. Позиция X начинается и центрируется на 0 для первой группы столбцов (2013) и занимает единицу. У нас есть буфер 0.1 с каждой стороны, а столбцов 5, следовательно, каждый столбец имеет ширину 0,16.

g = sns.catplot(x='year', y='income', data=df, kind='bar', hue='geo_name', legend=True)
#flatax=g.axes.flatten()
#g.axes[0].text=('1')
g.fig.set_size_inches(15,8)
g.fig.subplots_adjust(top=0.81,right=0.86)
g.ax.text(-0.5,51000,'X=-0.5')
g.ax.text(-0.4,49000,'X=-0.4')
g.ax.text(0,49000,'X=0')
g.ax.text(0.5,51000,'X=0.5')
g.ax.text(0.4,49000,'X=0.4')
g.ax.text(0.6,47000,'X=0.6')

limits

Текст по умолчанию выравнивается по левому краю (т. е. по установленному нами значению x). Здесь — это документация, если вы хотите поиграть с текстом (изменить шрифт, выравнивание и т. д.)

Затем мы можем найти правильное размещение для каждой метки, зная, что 3-й столбец каждой группы всегда будет центрироваться на единице (0,1,2,3,4).

g = sns.catplot(x='year', y='income', data=df, kind='bar', hue='geo_name', legend=True)
#flatax=g.axes.flatten()
#g.axes[0].text=('1')
g.fig.set_size_inches(15,8)
g.fig.subplots_adjust(top=0.81,right=0.86)
g.ax.text(-0.4,48411+500,'48,4K')
g.ax.text(-0.24,59055+500,'59,0K')
g.ax.text(-0.08,55003+500,'55,0K')
g.ax.text(0.08,37192+500,'37,2K')
g.ax.text(0.24,59055+500,'59,0K')

labelled

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

for i, yr in enumerate(df['year'].unique()):
    for j,gn in enumerate(df['geo_name'].unique()):

Теперь вы можете перебирать свою позицию x, используя: i-0.4+(j*0.16), и в то же время у вас есть значение для year и geo_name, чтобы получить правильное значение income.

Как я могу найти позицию x, чтобы правильно установить текст в цикле?

Sreeram TP 09.04.2019 10:57

@SreeramTP for i in range(0,df['year'].nunique()-1): for j in range(0,df['geo_name'].nunique()-1): print(i-0.4+(j*0.16))

CAPSLOCK 09.04.2019 11:04

Я сделал vals = df['income'].values.reshape(4, 5) for i in range(0,df['year'].nunique()): for j in range(0,df['geo_name'].nunique()): x = i-0.4+(j*0.16) g.ax.text(x, vals[i][j] + 500,'59,0K')

Sreeram TP 09.04.2019 11:19

Вы знаете, как изменить имя легенды.?

Sreeram TP 09.04.2019 11:22

@SreeramTP, вероятно, с g.fig.legend(title='title')

CAPSLOCK 09.04.2019 11:29

Я пытался это сделать, но это повторяет всю легенду еще раз

Sreeram TP 09.04.2019 11:37

изменить строку создания сюжета: g = sns.catplot(x='year', y='income', data=df, kind='bar', hue='geo_name', legend=False) и добавить следующую строку g.fig.legend(title='title',loc='right')

CAPSLOCK 09.04.2019 11:38

Мы можем использовать сетку Facet, возвращенную sns.catplot(), и выбрать ось. Используйте цикл for для позиционирования значения оси Y в нужном нам формате с помощью ax.text()

g = sns.catplot(x='year', y='income', data=data, kind='bar', hue='geo_name', legend=True)
g.fig.set_size_inches(16,8)
g.fig.subplots_adjust(top=0.81,right=0.86) 

ax = g.facet_axis(0,0)
for p in ax.patches:
    ax.text(p.get_x() - 0.01, 
            p.get_height() * 1.02, 
           '{0:.1f}K'.format(p.get_height()/1000),   #Used to format it K representation
            color='black', 
            rotation='horizontal', 
            size='large')

catplot demo

Ответ принят как подходящий

Обновлено matplotlib v3.4.2

  • Используйте matplotlib.pyplot.bar_label
  • Дополнительные параметры форматирования см. на странице matplotlib: демонстрация метки панели.
  • Протестировано с помощью pandas v1.2.4, который использует matplotlib в качестве сюжетного движка.
  • Используйте параметр fmt для простых форматов и параметр labels для индивидуального форматирования строк.
  • См. Добавление меток значений на гистограмму matplotlib для других параметров графика, связанных с новым методом.

Только для одного участка

g = sns.catplot(x='year', y='income', data=df, kind='bar', hue='geo_name', legend=True)
g.fig.set_size_inches(15, 8)
g.fig.subplots_adjust(top=0.81, right=0.86)

# extract the matplotlib axes_subplot objects from the FacetGrid
ax = g.facet_axis(0, 0)

# iterate through the axes containers
for c in ax.containers:
    labels = [f'{(v.get_height() / 1000):.1f}K' for v in c]
    ax.bar_label(c, labels=labels, label_type='edge')

Для одного или нескольких участков

g = sns.catplot(x='year', y='income', data=df, kind='bar', col='geo_name', col_wrap=3, legend=True)
g.fig.set_size_inches(15, 8)
g.fig.subplots_adjust(top=0.9)

g.fig.suptitle('Bar Count with Annotations')

# iterate through axes
for ax in g.axes.ravel():
    
    # add annotations
    for c in ax.containers:
        labels = [f'{(v.get_height() / 1000):.1f}K' for v in c]
        ax.bar_label(c, labels=labels, label_type='edge')
    ax.margins(y=0.2)

plt.show()

Другие вопросы по теме