Добавьте легенду в линейчатую диаграмму со списком Seaborn

#python #pandas #seaborn

Вопрос:

Я пытаюсь добавить легенду в свою линейчатую диаграмму seaborn bar , но получаю только ошибку «Не найдено маркеров с надписями, которые можно было бы поместить в легенду». что бы я ни пытался. Как это сделать?

 from pathlib import Path
import pandas as pd
import seaborn as sns
from matplotlib import pyplot as plt
import matplotlib.dates as mdates
import numpy as np    

dfGroup = pd.DataFrame({
        'Year': [1910, 1911, 1912, 1913, 1914, 1915, 1916, 1917, 1918, 1919, 1920],
        'Total Deaths': [0, 0, 2, 3, 2, 3, 4, 5, 6, 7, 8],
        'Total Affected': [0, 1, 0, 2, 3, 6, 9, 8, 12, 13, 15]
        })
# Add 3-year rolling average
dfGroup['rolling_3years'] = dfGroup['Total Deaths'].rolling(3).mean().shift(0)
dfGroup = dfGroup.fillna(0)

# Make a smooth line from the 3-year rolling average
from scipy.interpolate import make_interp_spline
X_Y_Spline = make_interp_spline(dfGroup['Year'], dfGroup['rolling_3years'])
 
# Returns evenly spaced numbers over a specified interval.
X_ = np.linspace(dfGroup['Year'].min(), dfGroup['Year'].max(), 500)
Y_ = X_Y_Spline(X_)

# Plot the data
a4_dims = (15, 10)
fig, ax1 = plt.subplots(figsize=a4_dims)

ax1 = sns.barplot(x = "Year", y = "Total Deaths",
             data = dfGroup, color='#42b7bd')
ax2 = ax1.twinx()
ax2 = sns.lineplot(X_, Y_, marker='o')
 

Ответ №1:

Поскольку сиборн barplot использует категориальные позиции, внутренне пронумерованные 0,1,2,... оба графика могут быть нарисованы на одном и том же ax . Это может быть достигнуто путем пересчета x значений для lineplot .

Для получения легенды label= следует использовать ключевое слово. (Создание легенды на twinx осях немного сложнее и потребует создания пользовательских дескрипторов.) Сиборн часто автоматически создает легенду. Если вы хотите изменить его внешний вид, вы можете позвонить ax1.legend(...) с параметрами настройки.

Вот несколько примеров кода:

 from pathlib import Path
import pandas as pd
import seaborn as sns
from matplotlib import pyplot as plt
import matplotlib.dates as mdates
import numpy as np

dfGroup = pd.DataFrame({
    'Year': [1910, 1911, 1912, 1913, 1914, 1915, 1916, 1917, 1918, 1919, 1920],
    'Total Deaths': [0, 0, 2, 3, 2, 3, 4, 5, 6, 7, 8],
    'Total Affected': [0, 1, 0, 2, 3, 6, 9, 8, 12, 13, 15]
})
# Add 3-year rolling average
dfGroup['rolling_3years'] = dfGroup['Total Deaths'].rolling(3).mean().shift(0)
dfGroup = dfGroup.fillna(0)

# Make a smooth line from the 3-year rolling average
from scipy.interpolate import make_interp_spline

X_Y_Spline = make_interp_spline(dfGroup['Year'], dfGroup['rolling_3years'])

# Returns evenly spaced numbers over a specified interval.
X_ = np.linspace(dfGroup['Year'].min(), dfGroup['Year'].max(), 500)
Y_ = X_Y_Spline(X_)

# Plot the data
a4_dims = (15, 10)
fig, ax1 = plt.subplots(figsize=a4_dims)
sns.barplot(x="Year", y="Total Deaths",
            data=dfGroup, color='#42b7bd', label='Barplot label', ax=ax1)
x_plot = np.linspace(0, len(dfGroup) - 1, len(X_))
sns.lineplot(x=x_plot, y=Y_, marker='o', label='LinePlot label', ax=ax1)
ax1.set_ylim(ymin=0) # let bars touch the bottom of the plot
ax1.margins(x=0.02) # less margins left and right
# ax1.legend(title='legend title') # optionally change the legend
plt.show()
 

sns.barplot с sns.линейной диаграммой и легендой

PS: Если an ax уже создан, его следует указать в качестве параметра для функций уровня осей seaborn (поэтому sns.barplot(..., ax=ax1) вместо ax1 = sns.barplot(...) .