Seaborn Barplot - отображение значений
Я смотрю, как сделать две вещи в Seaborn с использованием гистограммы для отображения значений, которые находятся в кадре данных, но не в графике
1) Я хочу отобразить значения одного поля в кадре данных при построении графика другого. Например, ниже я отображаю график "tip", но я бы хотел разместить значение "total_bill" с центром над каждым из баров (т.е. 325,88 выше пятницы, 1778,40 выше субботы и т.д.)
2) Есть ли способ масштабировать цвета баров, при этом самое низкое значение "total_bill" имеет самый светлый цвет (в данном случае пятница), а самое высокое значение "total_bill" - самое темное. Очевидно, что я буду придерживаться одного цвета (то есть синего), когда я делаю масштабирование.
Спасибо! Я уверен, что это легко, но мне не хватает этого..
Хотя я вижу, что другие считают, что это дубликат другой проблемы (или двух), я упускаю часть того, как я использую значение, которого нет на графике, в качестве основы для метки или затенения. Как я могу сказать, используйте total_bill в качестве основы. Извините, но я просто не могу понять это на основании этих ответов.
Начиная со следующего кода,
import pandas as pd
import seaborn as sns
%matplotlib inline
df=pd.read_csv("https://raw.githubusercontent.com/wesm/pydata- book/master/ch08/tips.csv", sep=',')
groupedvalues=df.groupby('day').sum().reset_index()
g=sns.barplot(x='day',y='tip',data=groupedvalues)
Я получаю следующий результат:
![enter image description here]()
Временное решение:
for index, row in groupedvalues.iterrows():
g.text(row.name,row.tip, round(row.total_bill,2), color='black', ha="center")
![enter image description here]()
На затенении, используя приведенный ниже пример, я попробовал следующее:
import pandas as pd
import seaborn as sns
%matplotlib inline
df=pd.read_csv("https://raw.githubusercontent.com/wesm/pydata-book/master/ch08/tips.csv", sep=',')
groupedvalues=df.groupby('day').sum().reset_index()
pal = sns.color_palette("Greens_d", len(data))
rank = groupedvalues.argsort().argsort()
g=sns.barplot(x='day',y='tip',data=groupedvalues)
for index, row in groupedvalues.iterrows():
g.text(row.name,row.tip, round(row.total_bill,2), color='black', ha="center")
Но это дало мне следующую ошибку:
AttributeError: у объекта DataFrame нет атрибута argsort
Итак, я попробовал модификацию:
import pandas as pd
import seaborn as sns
%matplotlib inline
df=pd.read_csv("https://raw.githubusercontent.com/wesm/pydata-book/master/ch08/tips.csv", sep=',')
groupedvalues=df.groupby('day').sum().reset_index()
pal = sns.color_palette("Greens_d", len(data))
rank=groupedvalues['total_bill'].rank(ascending=True)
g=sns.barplot(x='day',y='tip',data=groupedvalues,palette=np.array(pal[::-1])[rank])
и это оставляет меня с
IndexError: индекс 4 выходит за пределы оси 0 с размером 4
Ответы
Ответ 1
Давайте придерживаться решения из связанного вопроса (Изменение цветовой шкалы на графике морского бора). Вы хотите использовать argsort, чтобы определить порядок цветов, используемых для окрашивания полос. В связанном вопросе argsort применяется к объекту Series, который работает нормально, в то время как здесь у вас есть DataFrame. Поэтому вам нужно выбрать один столбец этого DataFrame, чтобы применить argsort.
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
df = sns.load_dataset("tips")
groupedvalues=df.groupby('day').sum().reset_index()
pal = sns.color_palette("Greens_d", len(groupedvalues))
rank = groupedvalues["total_bill"].argsort().argsort()
g=sns.barplot(x='day',y='tip',data=groupedvalues, palette=np.array(pal[::-1])[rank])
for index, row in groupedvalues.iterrows():
g.text(row.name,row.tip, round(row.total_bill,2), color='black', ha="center")
plt.show()
![enter image description here]()
Вторая попытка также работает нормально, единственная проблема заключается в том, что ранг, возвращаемый rank()
начинается с 1
а не с нуля. Таким образом, нужно вычесть 1 из массива. Также для индексации нам нужны целочисленные значения, поэтому нам нужно привести его к int
. rank = groupedvalues['total_bill'].rank(ascending=True).values
rank = (rank-1).astype(np.int)
Ответ 2
Работает с одним топором или с матрицей топора (подзаговоры)
from matplotlib import pyplot as plt
import numpy as np
def show_values_on_bars(axs):
def _show_on_single_plot(ax):
for p in ax.patches:
_x = p.get_x() + p.get_width() / 2
_y = p.get_y() + p.get_height()
value = '{:.2f}'.format(p.get_height())
ax.text(_x, _y, value, ha="center")
if isinstance(axs, np.ndarray):
for idx, ax in np.ndenumerate(axs):
_show_on_single_plot(ax)
else:
_show_on_single_plot(axs)
fig, ax = plt.subplots(1, 2)
show_values_on_bars(ax)
Ответ 3
На всякий случай, если кто-то заинтересован в маркировке горизонтального графика, я изменил ответ Шарона, как показано ниже:
def show_values_on_bars(axs, h_v="v", space=0.4):
def _show_on_single_plot(ax):
if h_v == "v":
for p in ax.patches:
_x = p.get_x() + p.get_width() / 2
_y = p.get_y() + p.get_height()
value = int(p.get_height())
ax.text(_x, _y, value, ha="center")
elif h_v == "h":
for p in ax.patches:
_x = p.get_x() + p.get_width() + float(space)
_y = p.get_y() + p.get_height()
value = int(p.get_width())
ax.text(_x, _y, value, ha="left")
if isinstance(axs, np.ndarray):
for idx, ax in np.ndenumerate(axs):
_show_on_single_plot(ax)
else:
_show_on_single_plot(axs)
Два параметра объяснили:
h_v
- горизонтальный или вертикальный барплот "h"
представляет горизонтальный график, "v"
представляет вертикальный график.
space
- пространство между текстом значения и верхним краем панели. Работает только в горизонтальном режиме.
Пример:
show_values_on_bars(sns_t, "h", 0.3)
![enter image description here]()
Ответ 4
Надеюсь, что это поможет для пункта № 2:
a) Вы можете сортировать по общей сумме, затем reset индекс в этот столбец
б) Используйте палитру = "Синий", чтобы использовать этот цвет, чтобы масштабировать диаграмму от светло-голубого до синего (если синий или синий, а затем используйте палитру = "Blues_d" )
import pandas as pd
import seaborn as sns
%matplotlib inline
df=pd.read_csv("https://raw.githubusercontent.com/wesm/pydata-book/master/ch08/tips.csv", sep=',')
groupedvalues=df.groupby('day').sum().reset_index()
groupedvalues=groupedvalues.sort_values('total_bill').reset_index()
g=sns.barplot(x='day',y='tip',data=groupedvalues, palette="Blues")