Chendo
Chendo

Reputation: 45

Combine lineplot and area plot in Python

I have the following dataframe showing a certain measure for two indices for each day, and the respective difference between the indices at the very right. Just showing a few days for simplicity purposes.

eff_date Index A Index B B minus A
2024-10-01 91 111 20
2024-10-02 88 110 22
2024-10-03 87 109 22
2024-10-04 84 107 23
2024-10-07 82 106 24

I have used the dataframe above to create a lineplot showing 'B-A' on the secondary y-axis. Output with slightly different data below. Is it possible though to make 'B-A' an area chart instead of a lineplot? I basically want the area below 'B-A' filled (and not necessarily showing the 'B-A' line anymore, if possible.

df = df.rename(columns={"eff_date":"Date"})
plt.figure(figsize = (12,6))
plot = sns.lineplot(x = 'Date', y = 'Index A', data = df, label = 'Index A')
sns.lineplot(x = 'Date', y = 'Index B', data = df, label = 'Index B')
ax2 = plt.twinx()
sns.lineplot(x = 'Date', y = 'B-A', data = df, color='r', ax=ax2)

plt.xticks(rotation=45)

plot.set(xlabel = 'Date', ylabel = 'Measure')

enter image description here

Upvotes: 0

Views: 45

Answers (1)

JohanC
JohanC

Reputation: 80449

You could extract the curve drawn, and then work with matplotlib's fill_between() to draw the area. (Note that sns.lineplot() doesn't return a plot. It returns the matplotlib ax onto which the plot was drawn.)

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

df = pd.DataFrame({'Date': ['2024-10-01', '2024-10-02', '2024-10-03', '2024-10-04', '2024-10-07'],
                   'Index A': [91, 88, 87, 84, 82],
                   'Index B': [111, 110, 109, 107, 106],
                   'B minus A': [20, 22, 22, 23, 24]})

plt.figure(figsize=(12, 6))
ax = sns.lineplot(x='Date', y='Index A', data=df, label='Index A')
sns.lineplot(x='Date', y='Index B', data=df, label='Index B', ax=ax)

ax2 = ax.twinx()
sns.lineplot(x='Date', y='B minus A', data=df, color='r', ax=ax2)
line = ax2.get_lines()[0]
ax2.fill_between(line.get_xdata(), 0, line.get_ydata(),
                 color='r', alpha=0.1, label='B minus A')
line.remove()  # remove the curve, keeping the area plot

handles1, labels1 = ax.get_legend_handles_labels()
handles2, labels2 = ax2.get_legend_handles_labels()
ax.legend(handles=handles1 + handles2, labels=labels1 + labels2, loc='upper left', bbox_to_anchor=(1.03, 1))
plt.tight_layout()
plt.show()

filled area via seaborn

Upvotes: 0

Related Questions