I want to use axvspan() function to visualize a DataFrame that I obtained using Pandas DataReader.But when I use the the following codes, I saw an error and there is no shading in subplots. What should I do? Thank you.
import matplotlib.pyplot as plt import pandas_datareader.data as pdr import pandas as pd import datetime start = datetime.datetime (2000,1,1) end = datetime.datetime (2021,5,1) df = pdr.DataReader(['WFRBSB50215', 'WFRBST01134','WFRBST01122', 'WFRBSN09139', 'WFRBSB50189', 'WFRBST01110','WFRBSB50191'],'fred',start, end) df.columns = ['Share of Total Net Worth Held by the Bottom 50% (1st to 50th Wealth Percentiles)', 'Share of Total Net Worth Held by the Top 1% (99th to 100th Wealth Percentiles)', 'Share of Corporate Equities and Mutual Fund Shares Helb By Top1%(99th to 100th Wealth Percentiles)', 'Share of Financial Assets Held by the 90th to 99th Wealth Percentiles', 'Share of Total Assets Held by the Bottom 50% (1st to 50th Wealth Percentiles)', 'Share of Real Estate Held by the Top 1% (99th to 100th Wealth Percentiles)', 'Share of Real Estate Held by the Bottom %50(1st to 50th Wealth Percentiles)' ] ax = df.plot(subplots=True, layout=(7,1), figsize=(15,15), linewidth=3.5, colormap="summer") ax.axvspan('2007-1-12', '2009-6-1', color='c', alpha=0.5) ax.axvspan('2019-12-1', '2020-2-1',color= 'orange', alpha=0.5) plt.xlabel('Date') ax[0,].set_title('Share of Total Net Worth Held by the Bottom 50%') ax[0,].set_ylabel('Percent of Aggregate') ax[1,].set_title('Share of Total Net Worth Held by the Top 1%') ax[1,].set_ylabel('Percent of Aggregate') ax[2,].set_title('Share of Corporate Equities and Mutual Fund Shares Helb By Top 1%') ax[2,].set_ylabel('Percent of Aggregate') ax[3,].set_title('Share of Financial Assets Held by the 90th to 99th Wealth Percentiles') ax[3,].set_ylabel('Percent of Aggregate') ax[4,].set_title('Share of Total Assets Held by the Bottom 50% ') ax[4,].set_ylabel('Percent of Aggregate') ax[5,].set_title('Share of Real Estate Held by the Top 1%') ax[5,].set_ylabel('Percent of Aggregate') ax[6,].set_title('Share of Real Estate Held by the Bottom %50') ax[6,].set_ylabel('Percent of Aggregate') plt.tight_layout() plt.style.use('seaborn-white') plt.show()
Advertisement
Answer
Try looping over all Subplots and adding axvspan
to the specific AxesSubplot
instead:
axes = df.plot(subplots=True, layout=(7, 1), figsize=(15, 15), linewidth=3.5, colormap="summer", ylabel='Percent of Aggregate', xlabel='Date') for (ax,), col in zip(axes, df.columns): ax.axvspan('2007-1-12', '2009-6-1', color='c', alpha=0.5) ax.axvspan('2019-12-1', '2020-2-1', color='orange', alpha=0.5) ax.set_title(col) plt.tight_layout() plt.style.use('seaborn-white') plt.show()
Some slight code reduction using the ylabel
and xlabel
kwargs of plot
and also setting subplot titles from df.columns
instead of manually.
Adding legend for axvspan
. The simplest approach is to add a label to each axvspan
and make the legend at the end of each iteration:
axes = df.plot(subplots=True, layout=(7, 1), figsize=(15, 15), linewidth=3.5, colormap="summer", ylabel='Percent of Aggregate', xlabel='Date', legend=False) for (ax,), col in zip(axes, df.columns): ax.axvspan('2007-1-12', '2009-6-1', color='c', alpha=0.5, label='2008 Crisis') ax.axvspan('2019-12-1', '2020-2-1', color='orange', alpha=0.5, label='Pandemic') ax.set_title(col) ax.legend() plt.style.use('seaborn-white') plt.tight_layout() plt.show()
Alternatively a single legend can be made for just the Crises:
fig, axes = plt.subplots(nrows=7, figsize=(15, 15)) df.plot(subplots=True, ax=axes, linewidth=3.5, colormap="summer", ylabel='Percent of Aggregate', xlabel='Date') for ax, col in zip(axes, df.columns): ax.axvspan('2007-1-12', '2009-6-1', color='c', alpha=0.5, label='2008 Crisis') ax.axvspan('2019-12-1', '2020-2-1', color='orange', alpha=0.5, label='Pandemic') ax.set_title(col) handles, labels = axes[-1].get_legend_handles_labels() fig.legend(handles[-2:], labels[-2:], title='Crises', loc='lower left', ncol=2) plt.style.use('seaborn-white') plt.tight_layout() plt.show()
^ Single legend is here in the lower left.