7

I'm plotting time series data using seaborn lineplot (https://seaborn.pydata.org/generated/seaborn.lineplot.html), and plotting the median instead of mean. Example code:

import seaborn as sns; sns.set()
import matplotlib.pyplot as plt

fmri = sns.load_dataset("fmri")
ax = sns.lineplot(x="timepoint", y="signal", estimator = np.median, data=fmri)

I want the error bands to show the interquartile range as opposed to the confidence interval. I know I can use ci = "sd" for standard deviation, but is there a simple way to add the IQR instead? I cannot figure it out.

Thank you!

firefly
  • 339
  • 2
  • 10
  • I don't think you can do it through `lineplot`. You will probably have to calculate it yourself and draw it onto the plot using matplotlib – DavidG May 19 '20 at 10:28

4 Answers4

12

I don't know if this can be done with seaborn alone, but here's one way to do it with matplotlib, keeping the seaborn style. The describe() method conveniently provides summary statistics for a DataFrame, among them the quartiles, which we can use to plot the medians with inter-quartile-ranges.

import seaborn as sns; sns.set()
import matplotlib.pyplot as plt

fmri = sns.load_dataset("fmri")
fmri_stats = fmri.groupby(['timepoint']).describe()

x = fmri_stats.index
medians = fmri_stats[('signal', '50%')]
medians.name = 'signal'
quartiles1 = fmri_stats[('signal', '25%')]
quartiles3 = fmri_stats[('signal', '75%')]

ax = sns.lineplot(x, medians) 
ax.fill_between(x, quartiles1, quartiles3, alpha=0.3); 

quartile plot

Arne
  • 9,990
  • 2
  • 18
  • 28
6

You can calculate the median within lineplot like you have done, set ci to be none and fill in using ax.fill_between()

import numpy as np
import seaborn as sns; sns.set()
import matplotlib.pyplot as plt

fmri = sns.load_dataset("fmri")
ax = sns.lineplot(x="timepoint", y="signal", estimator = np.median, 
                  data=fmri,ci=None)

bounds = fmri.groupby('timepoint')['signal'].quantile((0.25,0.75)).unstack()
ax.fill_between(x=bounds.index,y1=bounds.iloc[:,0],y2=bounds.iloc[:,1],alpha=0.1)

enter image description here

StupidWolf
  • 45,075
  • 17
  • 40
  • 72
  • This is great, thank you! I'm not sure if I should accept yours or @Arne's answer as the correct one given they're similar? – firefly May 19 '20 at 12:50
1

This option is possible since version 0.12 of seaborn, see here for the documentation.

pip install --upgrade seaborn

The estimator specifies the point by the name of pandas method or callable, such as 'median' or 'mean'.

The errorbar is an option to plot a distribution spread by a string, (string, number) tuple, or callable. In order to mark the median value and fill the area between the interquartile, you would need the params:

import seaborn as sns; sns.set()
import matplotlib.pyplot as plt

fmri = sns.load_dataset("fmri")
ax = sns.lineplot(data=fmri, x="timepoint", y="signal", estimator=np.median, 
                  errorbar=lambda x: (np.quantile(x, 0.25), np.quantile(x, 0.75)))

enter image description here

0

You can now!

estimator="median", errobar=("pi",0.5)

https://seaborn.pydata.org/tutorial/error_bars

KieserS
  • 41
  • 5