0

I am using python for a simple time-series analysis of calory intake. I am plotting the time series and the rolling mean/std over time. It looks like this:enter image description here

Here is how I do it:

## packages & libraries
import pandas as pd
import numpy as np
import matplotlib.pylab as plt
from pandas import Series, DataFrame, Panel


## import data and set time series structure
data = pd.read_csv('time_series_calories.csv',  parse_dates={'dates': ['year','month','day']}, index_col=0)


## check ts for stationarity

from statsmodels.tsa.stattools import adfuller
def test_stationarity(timeseries):
    
    #Determing rolling statistics
    rolmean = pd.rolling_mean(timeseries, window=14)
    rolstd = pd.rolling_std(timeseries, window=14)

    #Plot rolling statistics:
    orig = plt.plot(timeseries, color='blue',label='Original')
    mean = plt.plot(rolmean, color='red', label='Rolling Mean')
    std = plt.plot(rolstd, color='black', label = 'Rolling Std')
    plt.legend(loc='best')
    plt.title('Rolling Mean & Standard Deviation')
    plt.show()

The plot doesn't look good - since the rolling std distorts the scale of variation and the x-axis labelling is screwed up. I have two question: (1) How can I plot the rolling std on a secony y-axis? (2) How can I fix the x-axis overlapping labeling?

EDIT

With your help I managed to get the following: enter image description here

But do I get the legend sorted out?

Community
  • 1
  • 1
Rachel
  • 1,937
  • 7
  • 31
  • 58
  • 1
    A hacky way to get your legend to look ok could be to put `frameon=False` when you make the legend for 'Rolling Std' (or you could just do it for both legends). – Angus Williams Oct 13 '16 at 14:37

1 Answers1

1

1) Making a second (twin) axis can be done with ax2 = ax1.twinx(), see here for an example. Is this what you needed?

2) I believe there are several old answers to this question, i.e. here, here and here. According to the links provided, the easiest way is probably to use either plt.xticks(rotation=70) or plt.setp( ax.xaxis.get_majorticklabels(), rotation=70 ) or fig.autofmt_xdate().

import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot([1, 2, 3, 4, 5], [1, 2, 3, 4, 5])
plt.xticks(rotation=70)  # Either this 
ax.set_xticks([1, 2, 3, 4, 5])
ax.set_xticklabels(['aaaaaaaaaaaaaaaa','bbbbbbbbbbbbbbbbbb','cccccccccccccccccc','ddddddddddddddddddd','eeeeeeeeeeeeeeeeee'])
# fig.autofmt_xdate()  # or this
# plt.setp( ax.xaxis.get_majorticklabels(), rotation=70 )  # or this works
fig.tight_layout()
plt.show()

Answer to Edit When sharing lines between different axes into one legend is to create some fake-plots into the axis you want to have the legend as:

ax1.plot(something, 'r--')  # one plot into ax1
ax2.plot(something else, 'gx')  # another into ax2

# create two empty plots into ax1
ax1.plot([][], 'r--', label='Line 1 from ax1')  # empty fake-plot with same lines/markers as first line you want to put in legend
ax1.plot([][], 'gx', label='Line 2 from ax2')  # empty fake-plot as line 2 
ax1.legend()

In my silly example it is probably better to label the original plot in ax1, but I hope you get the idea. The important thing is to create the "legend-plots" with the same line and marker settings as the original plots. Note that the fake-plots will not be plotted since there is no data to plot.

Community
  • 1
  • 1
pathoren
  • 1,634
  • 2
  • 14
  • 22
  • thank you! That already helps me quite a bit. Any ideas on how to get a second y-axis for the rolling std? – Rachel Oct 13 '16 at 12:13
  • I realised I forgot to answer that question. Please see updated answer. – pathoren Oct 13 '16 at 12:14
  • Thank you, that already works really well! However, how do I get the legends combined? (see edited pic in OP) – Rachel Oct 13 '16 at 12:21