Issue
I have a simple FacetGrid of 2 row and 1 column with lineplots denoting different categories for the facets - image below.
# lineplot for each Category over the last three years
g = sns.FacetGrid(df, row="Category", sharey=False, sharex=False, height=2.5, aspect = 3)
g = g.map(plt.plot, 'Date', 'Count')
How do I add a reference line and annotation showing the mean Count for each facet?
Sample Data
- Read the sample dataframe with
df = pd.read_html('https://stackoverflow.com/q/59058641/7758804')[0]
df.Date = pd.to_datetime(df.Date).dt.date
Category | Date | Count |
---|---|---|
Group 1 | 2017-01-31 | 226 |
Group 1 | 2017-02-28 | 235 |
Group 1 | 2017-03-31 | 236 |
Group 1 | 2017-04-30 | 221 |
Group 1 | 2017-05-31 | 187 |
Group 1 | 2017-06-30 | 218 |
Group 1 | 2017-07-31 | 225 |
Group 1 | 2017-08-31 | 221 |
Group 1 | 2017-09-30 | 248 |
Group 1 | 2017-10-31 | 224 |
Group 1 | 2017-11-30 | 204 |
Group 1 | 2017-12-31 | 224 |
Group 1 | 2018-01-31 | 218 |
Group 1 | 2018-02-28 | 241 |
Group 1 | 2018-03-31 | 196 |
Group 1 | 2018-04-30 | 246 |
Group 1 | 2018-05-31 | 256 |
Group 1 | 2018-06-30 | 217 |
Group 1 | 2018-07-31 | 229 |
Group 1 | 2018-08-31 | 230 |
Group 1 | 2018-09-30 | 222 |
Group 1 | 2018-10-31 | 215 |
Group 1 | 2018-11-30 | 226 |
Group 1 | 2018-12-31 | 227 |
Group 1 | 2019-01-31 | 232 |
Group 1 | 2019-02-28 | 233 |
Group 1 | 2019-03-31 | 224 |
Group 1 | 2019-04-30 | 214 |
Group 1 | 2019-05-31 | 243 |
Group 1 | 2019-06-30 | 214 |
Group 1 | 2019-07-31 | 235 |
Group 1 | 2019-08-31 | 218 |
Group 1 | 2019-09-30 | 208 |
Group 2 | 2017-01-31 | 208 |
Group 2 | 2017-02-28 | 254 |
Group 2 | 2017-03-31 | 223 |
Group 2 | 2017-04-30 | 227 |
Group 2 | 2017-05-31 | 245 |
Group 2 | 2017-06-30 | 222 |
Group 2 | 2017-07-31 | 226 |
Group 2 | 2017-08-31 | 235 |
Group 2 | 2017-09-30 | 225 |
Group 2 | 2017-10-31 | 226 |
Group 2 | 2017-11-30 | 258 |
Group 2 | 2017-12-31 | 234 |
Group 2 | 2018-01-31 | 257 |
Group 2 | 2018-02-28 | 224 |
Group 2 | 2018-03-31 | 228 |
Group 2 | 2018-04-30 | 222 |
Group 2 | 2018-05-31 | 227 |
Group 2 | 2018-06-30 | 256 |
Group 2 | 2018-07-31 | 217 |
Group 2 | 2018-08-31 | 243 |
Group 2 | 2018-09-30 | 230 |
Group 2 | 2018-10-31 | 250 |
Group 2 | 2018-11-30 | 197 |
Group 2 | 2018-12-31 | 232 |
Group 2 | 2019-01-31 | 248 |
Group 2 | 2019-02-28 | 232 |
Group 2 | 2019-03-31 | 259 |
Group 2 | 2019-04-30 | 259 |
Group 2 | 2019-05-31 | 229 |
Group 2 | 2019-06-30 | 228 |
Group 2 | 2019-07-31 | 234 |
Group 2 | 2019-08-31 | 218 |
Group 2 | 2019-09-30 | 231 |
Solution
- As per the Warning in
seaborn.FacetGrid
, it is better to use figure-level functions likesns.relplot
.
g = sns.relplot(data=df, kind='line', x='Date', y='Count', row='Category', height=2.5, aspect=3, facet_kws={'sharey': True, 'sharex': False})
g.fig.tight_layout()
# draw lines:
for m, ax in zip(df.groupby('Category').Count.mean(), g.axes.ravel()):
ax.hlines(m, *ax.get_xlim())
ax.annotate(f'Mean: {m:0.0f}', xy=(ax.get_xlim()[1], m))
- This also works for other figure-level plots like
sns.catplot
.
g = sns.catplot(data=df, kind='bar', x='Date', y='Count', row='Category', height=2.5, aspect=3)
g.set_xticklabels(rotation=90)
# draw lines:
for m, ax in zip(df.groupby('Category').Count.mean(), g.axes.ravel()):
ax.hlines(m, *ax.get_xlim())
ax.annotate(f'Mean: {m:0.0f}', xy=(ax.get_xlim()[1], m))
You can manually draw the horizontal line on each of the axes:
zip(list1, list2)
is similar to [(list1[0], list2[0]), (list1[1], list2[1]),...]
. In this code it means m is the mean, ax is the axis in the facets. ravel()
turns n-dimension np.array
into 1D array so you can zip
. ax.hlines(y_val, x_min, x_max)
draw a horizontal line at y_val
from x_min
to x_max
. Here the two x values are provided by *ax.get_xlim()
.
g = sns.FacetGrid(df, row="Category", sharey=False, sharex=False, height=2.5, aspect = 3)
g = g.map(plt.plot, 'Date', 'Count')
# draw lines:
for m,ax in zip(df.groupby('Category').Count.mean(), g.axes.ravel()):
ax.hlines(m,*ax.get_xlim())
Output:
Answered By - Quang Hoang
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.