Ответ 1
Разница между версиями Pandas и Statsmodels заключается в делении среднего вычитания и нормализации/дисперсии:
-
autocorr
делает не что иное, как прохождение подсерий исходной серии доnp.corrcoef
. Внутри этого метода среднее значение выборки и выборочная дисперсия этих подсерий используются для определения коэффициента корреляции -
acf
, наоборот, использует общее среднее выборочное среднее и выборочную дисперсию для определения коэффициента корреляции.
Различия могут уменьшиться для более длинных временных рядов, но они довольно большие для коротких.
По сравнению с Matlab функция Pandas autocorr
, вероятно, соответствует выполнению Matlabs xcorr
(cross-corr) с самой (отстающей) серией вместо Matlab autocorr
, которая вычисляет автокорреляцию образца (угадывание из документов, я не могу проверить это, потому что у меня нет доступа к Matlab).
См. этот MWE для пояснения:
import numpy as np
import pandas as pd
from statsmodels.tsa.stattools import acf
import matplotlib.pyplot as plt
plt.style.use("seaborn-colorblind")
def autocorr_by_hand(x, lag):
# Slice the relevant subseries based on the lag
y1 = x[:(len(x)-lag)]
y2 = x[lag:]
# Subtract the subseries means
sum_product = np.sum((y1-np.mean(y1))*(y2-np.mean(y2)))
# Normalize with the subseries stds
return sum_product / ((len(x) - lag) * np.std(y1) * np.std(y2))
def acf_by_hand(x, lag):
# Slice the relevant subseries based on the lag
y1 = x[:(len(x)-lag)]
y2 = x[lag:]
# Subtract the mean of the whole series x to calculate Cov
sum_product = np.sum((y1-np.mean(x))*(y2-np.mean(x)))
# Normalize with var of whole series
return sum_product / ((len(x) - lag) * np.var(x))
x = np.linspace(0,100,101)
results = {}
nlags=10
results["acf_by_hand"] = [acf_by_hand(x, lag) for lag in range(nlags)]
results["autocorr_by_hand"] = [autocorr_by_hand(x, lag) for lag in range(nlags)]
results["autocorr"] = [pd.Series(x).autocorr(lag) for lag in range(nlags)]
results["acf"] = acf(x, unbiased=True, nlags=nlags-1)
pd.DataFrame(results).plot(kind="bar", figsize=(10,5), grid=True)
plt.xlabel("lag")
plt.ylim([-1.2, 1.2])
plt.ylabel("value")
plt.show()
Посмотрите этот график для результата
Statsmodels использует np.correlate
для оптимизации, но в основном это работает.