Тот же масштаб для комбинированного графика twinx() с сиборном

#python #pandas #seaborn

Вопрос:

Давайте воспользуемся классическим примером еженедельных осадков:

 import pandas as pd
import seaborn as sns
from matplotlib import pyplot as plt
from random import randint

data = {
    'Week': [i for i in range(1,9)],
    'Weekly Precipitation': [randint(1,10) for i in range(1,9)]
}
df = pd.DataFrame(data)
 

Давайте также добавим столбец с накопленными осадками:

 df['Cumulative'] = df['Weekly Precipitation'].expanding(min_periods=2).sum()
 

Теперь предположим, что мне нужна одна диаграмма с гистограммой еженедельных осадков и линейной диаграммой с суммарными осадками. Поэтому я делаю это:

 fig, ax1 = plt.subplots(figsize=(10,5))
sns.barplot(x='Week', y='Weekly Precipitation', data=df, ax=ax1)
ax2 = ax1.twinx()
sns.lineplot(x='Week', y='Cumulative', data=df, ax=ax2)
 

Что дает этот сюжет:

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

И вы можете увидеть проблему: хотя оба ряда соизмеримы, обе оси x используют разный масштаб, что искажает визуализацию, так как линия всегда должна быть выше столбиков.

Итак, вместо двух осей я пытаюсь расположить оба графика на одной оси:

 fig, ax1 = plt.subplots(figsize=(10,5))
ax1.set_facecolor('white')
sns.barplot(x='Week', y='Weekly Precipitation', data=df, ax=ax1)
sns.lineplot(x='Week', y='Cumulative', data=df, ax=ax1)
ax1.set_ylabel('Precipitation')
 

Теперь, конечно, масштаб правильный (хотя я должен иметь дело с одной меткой y), но… второй участок сдвинут вправо на один тик!

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

Как это вообще имеет смысл?!

Комментарии:

1. попробуйте это: ax1.set_yticks(np.arange(ax2.get_yticks()[0], ax2.get_yticks()[-1], len(ax1.get_yticks())))

2. Спасибо, это почти работает. Однако, похоже, что мой линейный график сдвинут вправо на один тик, а тики y не совсем совпадают: i.imgur.com/HUfjcM7.png

3. Верно. Я перепробовал все, и это не улучшилось, поэтому я сделал комментарий. Если вы отредактируете вопрос так, как он есть сейчас, кто-то другой сможет ответить на него.

4. Теперь я попробовал код еще раз. Я создал его методом проб и ошибок, поэтому не могу объяснить, в чем его смысл. ax2.set_ylim(0, df['Cumulative'].max());ax2.grid(True);import matplotlib.ticker;nticks = 8;ax1.yaxis.set_major_locator(matplotlib.ticker.LinearLocator(nticks));ax2.yaxis.set_major_locator(matplotlib.ticker.LinearLocator(nticks))

5. Я не уверен, почему он смещается, но он исчезает, когда вы устанавливаете его на числовую ось X. xx = [0,1,2,3,4,5,6,7];sns.barplot(x=xx,...);sns.lineplot(x=xx,...)