#python #pandas #seaborn
Вопрос:
У меня есть гистограмма, и я хотел бы добавить горизонтальную линию в каждую из полос на основе значения столбца pandas. Я видел примеры того, как добавить одну горизонтальную линию по всем столбцам, но это не то, к чему я стремлюсь.
То, что я пробовал до сих пор, это:
import seaborn as sns
import pandas as pd
import matplotlib.pyplot as plt
df = pd.DataFrame([[1, 2, 1], [2, 4, 3], [3, 6, 1], [4, 8, 3]], columns=["X", "Value", "Hor"])
fig, ax = plt.subplots()
sns.barplot(x="X", y="Value", data=df, color='green', ax=ax)
sns.barplot(x="X", y="Hor", data=df, color='green', linewidth=2.5, edgecolor='black', ax=ax)
Это относительно близко к тому, что я хотел бы иметь, но я хочу только верхний край и желательно пунктирный.
Мой вопрос двоякий:
- Это способ сделать это? Укладывая два гистограммы друг на друга?
- Если это так, как я могу настроить все края так, чтобы они соответствовали тому, что мне нужно?
Ответ №1:
Вы можете перебирать исправления в своем barplot, извлекать ширину и положение и отображать свои значения с помощью plt.plot. Обратите внимание, что это приведет к разрыву, если фрейм данных не отсортирован.
import seaborn as sns
import pandas as pd
import matplotlib.pyplot as plt
df = pd.DataFrame([[1, 2, 1], [2, 4, 3], [3, 6, 1], [4, 8, 3]], columns=["X", "Value", "Hor"])
fig, ax = plt.subplots()
sns.barplot(x="X", y="Value", data=df, color='green', ax=ax)
for ix, a in enumerate(ax.patches):
x_start = a.get_x()
width = a.get_width()
ax.plot([x_start, x_start width], 2*[df.loc[ix, 'Hor']], '--', c='k')
Комментарии:
1. Это выглядит великолепно! По какой-то непонятной (для меня :)) причине в моих фактических данных я получаю ошибку, потому что ix переходит к значению, которое на единицу больше, чем строки фрейма данных. Я знаю, что на это, вероятно, сложно ответить, но у меня будет даже малейший намек на то, почему это может быть?
2. да, трудно сказать на расстоянии. Вы должны сгенерировать такое же количество столбцов, как и строк в вашем фрейме данных. Это число, в свою очередь, определяет, насколько высоко
ix
оно будет.3. Ну что ж, я думаю, это останется для меня загадкой. Я добавил разрыв (к моему стыду!). Спасибо!
Ответ №2:
Это может быть достигнуто с помощью hlines
на вашей оси, например, при переборе строк вашего фрейма данных. Код будет выглядеть следующим образом:
import seaborn as sns
import pandas as pd
import matplotlib.pyplot as plt
df = pd.DataFrame([[1, 2, 1], [2, 4, 3], [3, 6, 1], [4, 8, 3]], columns=["X", "Value", "Hor"])
fig, ax = plt.subplots()
sns.barplot(x="X", y="Value", data=df, color='green', ax=ax)
# iterate over range of number of rows
for i in range(len(df)):
ax.hlines(y = df.Hor[i], xmin = i-0.5, xmax = i 0.5,
color = 'black')
Когда вы строите гистограммы, координаты x начинаются с нуля для первого столбца с шагом в единицу. Эта информация может быть использована для назначения xmin
и xmax
для ax.hlines
, здесь в форме i
, которая идет от нуля до количества строк вашего фрейма данных минус один. Вы можете настроить 0.5
в соответствии с вашими потребностями, в зависимости от «ширины» желаемой линии.