Reputation: 69
I've tried filling in the area between two lines with Python -- using facetgrid on seaborn. My code is the following:
sns.set_style('white')
sns.set(font_scale=1.5, rc={"lines.linewidth": 1.5})
g = sns.FacetGrid(final, col = "Variable", col_wrap = 3, legend_out=True)
g.fig.set_figwidth(20)
g.fig.set_figheight(10)
g.map_dataframe(sns.lineplot, x = "Time", y="Shock", color='black')
g.map_dataframe(sns.lineplot, x = "Time", y="Upper confidence level", color='grey')
g.map_dataframe(sns.lineplot, x = "Time", y="Lower confidence level", color='grey')
line = (g.map_dataframe(sns.lineplot, x = "Time", y="Lower", color='grey')).get_lines()
g.map(plt.fill_between(line[0].get_xdata(), line[1].get_ydata(), line[2].get_ydata(), color='grey', alpha=.5))
g.map(plt.axhline, y=0, ls='--', c='red')
g.set_titles(col_template="{col_name}", row_template=["",""])
g.set(ylim=(-0.1, 0.1))
I get the following error: AttributeError: 'FacetGrid' object has no attribute 'get_lines'
Is there a way to apply the plt.fill_between
command on FacetGrid
?
Upvotes: 0
Views: 900
Reputation: 80339
For functions such as fill_between
, there is no way to directly execute them via g.map_dataframe
. Instead, you can create a custom function which then can be called via g.map_dataframe
. Such a custom function needs to accept at least 2 parameters:
data
: the dataframe restricted to the subplotcolor
: this is used when working with hue, but can be ignoredAs a custom function is needed anyway, it might make sense to do all the drawing inside that function. Especially when a lot of functions need to be called, such might be easier to read and to customize further.
Here is an example of how such code could look like. Note that the preferred way to set the figsize
is via the height=
and aspect=
keywords, indicating the height and the ratio between width and height of the individual subplots.
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np
def draw_subplot(data, color):
sns.lineplot(data=data, x="Time", y="Shock", color='black')
sns.lineplot(data=data, x="Time", y="Upper confidence level", color='grey')
sns.lineplot(data=data, x="Time", y="Lower confidence level", color='grey')
line = plt.gca().lines
plt.fill_between(line[0].get_xdata(), line[1].get_ydata(), line[2].get_ydata(), color='grey', alpha=.5)
plt.axhline(y=0, ls='--', c='red')
plt.margins(x=0)
sns.set_style('white')
sns.set(font_scale=1.5, rc={"lines.linewidth": 1.5})
final = pd.DataFrame({"Time": np.tile(np.arange(1, 81), 3),
"Shock": np.random.randn(80 * 3).cumsum() * 2,
"Variable": np.repeat([*'ABC'], 80)})
final["Upper confidence level"] = final["Shock"] + 2 + np.abs(np.random.randn(len(final)).cumsum())
final["Lower confidence level"] = final["Shock"] - 2 - np.abs(np.random.randn(len(final)).cumsum())
g = sns.FacetGrid(final, col="Variable", col_wrap=3, legend_out=True, height=6, aspect=1.5)
g.map_dataframe(draw_subplot)
g.set_titles(col_template="{col_name}", row_template=["", ""])
plt.show()
Upvotes: 1