import statsmodels.tsa.api as tsa
[docs]
def get_adfuller_results(ts, alpha=.05,
label='adfuller',
**kwargs):
"""Uses statsmodels' adfuller function to test a univariate time series for stationarity.
Null hypothesis:
The time series is NOT stationary. (It "has a unit root".)
Interpretation:
a p-value less than alpha (.05) means the ts IS stationary.
(We reject the null hypothesis that it is not stationary.)
Returns
-------
results (DataFrame): DataFrame with the following columns/results:
- "Test Statistic" : the adfuller test statistic.
- "# of Lags Used": The number of lags used in the calculation.
- "# of Observations" : The number of observations used.
- "p-value" : p-value for hypothesis test.
- "alpha": the significance level used for interpretin p-value
- "sig/stationary?": simplified interpretation of p-value
ADFULLER DOCUMENTATION:
For the full adfuller documentation, see:
https://www.statsmodels.org/dev/generated/statsmodels.tsa.stattools.adfuller.html
"""
import pandas as pd
# Saving each output
(test_stat, pval, nlags, nobs, crit_vals_d,
icbest )= tsa.adfuller(ts, **kwargs)
adfuller_results = {'Test Statistic': test_stat,
"# of Lags Used":nlags,
'# of Observations':nobs,
'p-value': round(pval,6),
'alpha': alpha,
'sig/stationary?': pval<alpha}
return pd.DataFrame(adfuller_results, index=[label])
# Update to include option for PACF
[docs]
def get_sig_lags(ts, type='ACF', nlags=None,alpha=0.5):
import pandas as pd
if type == 'ACF':
# Running the function used by plot_acf
corr_values, conf_int = tsa.stattools.acf(ts, alpha=alpha, nlags=nlags)
elif type=='PACF':
corr_values, conf_int = tsa.stattools.pacf(ts, alpha=alpha, nlags=nlags)
else:
raise Exception("type must be either 'ACF' or 'PACF'")
# Determine lags
lags =range(len(corr_values))
# Create a centered version of the acf_df [centered on..0??]
corr_df = pd.DataFrame({type:corr_values,
'Lags':lags,
'lower ci': conf_int[:,0]-corr_values, # subtract acf from lower ci to center
'upper ci': conf_int[:,1]-corr_values, # subtact acf to upper ci to center
})
corr_df = corr_df.set_index("Lags")
# Getting filter for sig lags
filter_sig_lags = (corr_df[type] < corr_df['lower ci']) | (corr_df[type] > corr_df['upper ci'])
# Get lag #'s
sig_lags= corr_df.index[filter_sig_lags]
sig_lags = sig_lags[sig_lags!=0]
return sig_lags
[docs]
def plot_acf_pacf(ts, nlags=40, figsize=(10, 5),
annotate_sig=False, alpha=.05,
acf_kws={}, pacf_kws={},
annotate_seas=False, m = None,
seas_color='black'):
import matplotlib.pyplot as plt
fig, axes = plt.subplots(nrows=2, figsize=figsize)
# Sig lags line style
sig_vline_kwargs = dict( ls=':', lw=1, zorder=0, color='red')
# ACF
tsa.graphics.plot_acf(ts, ax=axes[0], lags=nlags, **acf_kws)
## Annotating sig acf lags
if annotate_sig == True:
sig_acf_lags = get_sig_lags(ts,nlags=nlags,alpha=alpha, type='ACF')
for lag in sig_acf_lags:
axes[0].axvline(lag,label='sig', **sig_vline_kwargs )
# PACF
tsa.graphics.plot_pacf(ts,ax=axes[1], lags=nlags, **pacf_kws)
## Annotating sig pacf lags
if annotate_sig == True:
## ANNOTATING SIG LAGS
sig_pacf_lags = get_sig_lags(ts,nlags=nlags,alpha=alpha, type='PACF')
for lag in sig_pacf_lags:
axes[1].axvline(lag, label='sig', **sig_vline_kwargs)
### ANNOTATE SEASONS
if annotate_seas == True:
# Ensure m was defined
if m is None:
raise Exception("Must define value of m if annotate_seas=True.")
## Calculate number of complete seasons to annotate
n_seasons = nlags//m
# Seasonal Lines style
seas_vline_kwargs = dict( ls='--',lw=1, alpha=.7, color=seas_color, zorder=-1)
## for each season, add a line
for i in range(1, n_seasons+1):
axes[0].axvline(m*i, **seas_vline_kwargs, label="season")
axes[1].axvline(m*i, **seas_vline_kwargs, label="season")
fig.tight_layout()
return fig
[docs]
def regression_metrics_ts(ts_true, ts_pred, label="", verbose=True, output_dict=False,):
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score, mean_absolute_percentage_error
# Get metrics
mae = mean_absolute_error(ts_true, ts_pred)
mse = mean_squared_error(ts_true, ts_pred)
rmse = mean_squared_error(ts_true, ts_pred, squared=False)
r_squared = r2_score(ts_true, ts_pred)
mae_perc = mean_absolute_percentage_error(ts_true, ts_pred) * 100
if verbose == True:
# Print Result with label
header = "---" * 20
print(header, f"Regression Metrics: {label}", header, sep="\n")
print(f"- MAE = {mae:,.3f}")
print(f"- MSE = {mse:,.3f}")
print(f"- RMSE = {rmse:,.3f}")
print(f"- R^2 = {r_squared:,.3f}")
print(f"- MAPE = {mae_perc:,.2f}%")
if output_dict == True:
metrics = {
"Label": label,
"MAE": mae,
"MSE": mse,
"RMSE": rmse,
"R^2": r_squared,
"MAPE(%)": mae_perc,
}
return metrics