Я нарисовал 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)
Я получаю вывод, как показано ниже
Я хочу добавить значения каждой полосы вверху в представлении K. Например
в 2013
полоса для Michigan
находится на 48411
, поэтому я хочу добавить значение 48.4K
поверх этой полосы. Аналогично для всех баров.
Это грубое решение, но оно помогает.
Мы добавляем текст к объекту 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')
Текст по умолчанию выравнивается по левому краю (т. е. по установленному нами значению 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')
Конечно, вместо того, чтобы вручную маркировать все, вы должны прокручивать данные и автоматически создавать метки.
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
.
@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))
Я сделал 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')
Вы знаете, как изменить имя легенды.?
@SreeramTP, вероятно, с g.fig.legend(title='title')
Я пытался это сделать, но это повторяет всю легенду еще раз
изменить строку создания сюжета: g = sns.catplot(x='year', y='income', data=df, kind='bar', hue='geo_name', legend=False)
и добавить следующую строку g.fig.legend(title='title',loc='right')
Мы можем использовать сетку 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')
matplotlib v3.4.2
matplotlib.pyplot.bar_label
pandas v1.2.4
, который использует matplotlib
в качестве сюжетного движка.fmt
для простых форматов и параметр labels
для индивидуального форматирования строк.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()
Как я могу найти позицию
x
, чтобы правильно установить текст в цикле?