noob
noob

Reputation: 3811

Minor tick axis and major tick axis matplotlib formatting in Time series seasonal decomposition

df

Date        Col1   Col2   Col3
2016-11-1    12     13     14
2016-10-1    2      3      1
2016-03-01   2      1      1 
and so on

Code to decompose time series to get seasonality, trends, observed and residual values:

from statsmodels.tsa.seasonal import seasonal_decompose
from matplotlib import dates as mdates
years = mdates.YearLocator()    # only print label for the years
months = mdates.MonthLocator()  # mark months as ticks
years_fmt = mdates.DateFormatter('%Y')
fmt = mdates.DateFormatter('%b')

df = df.set_index('Date')


s_dec_multiplicative = seasonal_decompose(df['Col1'], model = "multiplicative")
s_dec_multiplicative.plot()

s_dec_multiplicative.xaxis.set_major_locator(years)
s_dec_multiplicative.xaxis.set_minor_locator(months)
s_dec_multiplicative.xaxis.set_major_formatter(years_fmt)
s_dec_multiplicative.xaxis.set_minor_formatter(fmt)
plt.show()

Problem: I want tickers for JAN,FEB, MAR etc like that for all months. Years should be mentioned like 2016, 2017 and so on and months should be in between with small ticks.

ERROR:

---> 12 s_dec_multiplicative.xaxis.set_major_locator(years)
AttributeError: 'DecomposeResult' object has no attribute 'xaxis'

Upvotes: 2

Views: 2029

Answers (1)

Sergey Bushmanov
Sergey Bushmanov

Reputation: 25209

Your problem is that you're trying to change attribute of DecomposeResult object whereas you're supposed to work on ax object.

Let's retrieve some toy time series data:

from pandas_datareader import data
goog = data.DataReader("GOOG", "yahoo")["Adj Close"]
goog.plot();

enter image description here

Now let's do the desired decomposition and put the results into Pandas' df:

from statsmodels.tsa.seasonal import seasonal_decompose
s_dec_multiplicative = seasonal_decompose(goog, model = "multiplicative", freq=12)

observed = s_dec_multiplicative.observed
seasonal = s_dec_multiplicative.seasonal
residual = s_dec_multiplicative.resid

df = pd.DataFrame({"observed":observed, "seasonal":seasonal,"residual":residual}

Finally, we're ready to plot:

from matplotlib import dates as mdates
years = mdates.YearLocator()    # only print label for the years
months = mdates.MonthLocator()  # mark months as ticks
years_fmt = mdates.DateFormatter('%Y-%b')
fmt = mdates.DateFormatter('%b')

_, axes = plt.subplots(nrows=3,ncols=1, figsize=(20, 10))
for i, ax in enumerate(axes):
    ax = df.iloc[:,i].plot(ax=ax)
    ax.xaxis.set_major_locator(years)
    ax.xaxis.set_major_formatter(years_fmt)
    ax.xaxis.set_minor_locator(months)
    ax.xaxis.set_minor_formatter(fmt)
    ax.set_ylabel(df.iloc[:,i].name)
    plt.setp(ax.xaxis.get_minorticklabels(), rotation=90)
    plt.setp(ax.xaxis.get_majorticklabels(), rotation=90)

enter image description here

Upvotes: 3

Related Questions