Matplotlib axvspan shading for pandas DataFrame subplots based on one of the columns

matplotlib, pandas, python, time-series

Solution

You're set up to do this very well. I think you'll need to interact with matplotlib directly, however.

If you set up your DataFrame like this (what you have already):

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

randBinList = lambda n: [np.random.randint(0,2) for b in range(1,n+1)]
rng = pd.date_range('1/1/2011', periods=72, freq='H')
ts = pd.DataFrame({
    'Value1': np.random.randn(len(rng)),
    'Value2': np.random.randn(len(rng)),
    'OnOff': randBinList(len(rng))
}, index=rng)

Then you you can use the `fill_between` command with the `where` kwarg:

fig, (ax1, ax2) = plt.subplots(nrows=2)
ax1.plot(ts.index, ts['Value1'], 'k-')
ax1.fill_between(ts.index, ts['Value1'], y2=-6, where=ts['OnOff'])

ax2.plot(ts.index, ts['Value2'], 'k-')
ax2.fill_between(ts.index, ts['Value2'], y2=-6, where=ts['OnOff'])
fig.tight_layout()

Which gives me:

Problem

What is the most elegant way to shade a pandas subplots based on one of the columns in a DataFrame? A simple example: ``` In [8]: from random import * import pandas as pd randBinList = lambda n: [randint(0,1) for b in range(1,n+1)] rng = pd.date_range('1/1/2011', periods=72, freq='H') ts = pd.DataFrame({'Value1': randn(len(rng)),'Value2': randn(len(rng)),'OnOff': randBinList(len(rng))}, index=rng) ts.plot(subplots=True) ``` Results in the following plot: Ideally, I would like a subplot of just `Value1` and `Value2` with both plots being shaded using `axvspan` where `On` (values with `1.0` in the `OnOff`) are shaded and `Off` is not shaded.

Original source