Инструменты вычислений
Статистические функции
Процентное изменение
Series, DataFrame, и Panel все имеют метод pct_change, для вычисления процентного изменения за заданное количество периодов (используя fill_method для заполнения значений NaN/null перед вычислением процентного изменения).
In [1]: ser = pd.Series(np.random.randn(8)) In [2]: ser.pct_change() Out[2]: 0 NaN 1 -1.602976 2 4.334938 3 -0.247456 4 -2.067345 5 -1.142903 6 -1.688214 7 -9.759729 dtype: float64
In [3]: df = pd.DataFrame(np.random.randn(10, 4))
In [4]: df.pct_change(periods=3)
Out[4]:
0 1 2 3
0 NaN NaN NaN NaN
1 NaN NaN NaN NaN
2 NaN NaN NaN NaN
3 -0.218320 -1.054001 1.987147 -0.510183
4 -0.439121 -1.816454 0.649715 -4.822809
5 -0.127833 -3.042065 -5.866604 -1.776977
6 -2.596833 -1.959538 -2.111697 -3.798900
7 -0.117826 -2.169058 0.036094 -0.067696
8 2.492606 -1.357320 -1.205802 -1.558697
9 -1.012977 2.324558 -1.003744 -0.371806
Ковариация
Объект Series имеет метод cov для вычисления ковариации между рядами (исключая значения NaN/null).
In [5]: s1 = pd.Series(np.random.randn(1000)) In [6]: s2 = pd.Series(np.random.randn(1000)) In [7]: s1.cov(s2) Out[7]: 0.00068010881743110698
Аналогично, DataFrame имеет метод cov для вычисления парных ковариаций между рядами в DataFrame, также исключая значения NaN/null.
Примечание
При предположении, что пропущенные данные отсутствуют случайным образом, это приводит к оценке ковариационной матрицы, которая является несмещенной. Однако для многих приложений эта оценка может быть неприемлемой, потому что оценка ковариационной матрицы не гарантирует положительную полуопределённость. Это может привести к тому, что оценки корреляций будут иметь абсолютные значения больше единицы и/или к необратимой ковариационной матрице. Смотрите Оценивание ковариационных матриц для получения более подробной информации.
In [8]: frame = pd.DataFrame(np.random.randn(1000, 5), columns=['a', 'b', 'c', 'd', 'e'])
In [9]: frame.cov()
Out[9]:
a b c d e
a 1.000882 -0.003177 -0.002698 -0.006889 0.031912
b -0.003177 1.024721 0.000191 0.009212 0.000857
c -0.002698 0.000191 0.950735 -0.031743 -0.005087
d -0.006889 0.009212 -0.031743 1.002983 -0.047952
e 0.031912 0.000857 -0.005087 -0.047952 1.042487
DataFrame.cov также поддерживает необязательное ключевое слово min_periods, которое определяет минимальное необходимое количество наблюдений для каждой пары столбцов для получения корректного результата.
In [10]: frame = pd.DataFrame(np.random.randn(20, 3), columns=['a', 'b', 'c'])
In [11]: frame.ix[:5, 'a'] = np.nan
In [12]: frame.ix[5:10, 'b'] = np.nan
In [13]: frame.cov()
Out[13]:
a b c
a 1.210090 -0.430629 0.018002
b -0.430629 1.240960 0.347188
c 0.018002 0.347188 1.301149
In [14]: frame.cov(min_periods=12)
Out[14]:
a b c
a 1.210090 NaN 0.018002
b NaN 1.240960 0.347188
c 0.018002 0.347188 1.301149
Корреляция
Предоставлены несколько методов для вычисления корреляций:
| Название метода | Описание |
|---|---|
pearson (default) | Коэффициент корреляции |
kendall | Коэффициент корреляции Кендалла |
spearman | Коэффициент ранговой корреляции Спирмена |
Все они в настоящее время вычисляются с использованием парных полных наблюдений.
Примечание
Пожалуйста, см. примечания, связанные с этим методом вычисления корреляционных матриц в разделе ковариации.
In [15]: frame = pd.DataFrame(np.random.randn(1000, 5), columns=['a', 'b', 'c', 'd', 'e'])
In [16]: frame.ix[::2] = np.nan
# Series with Series
In [17]: frame['a'].corr(frame['b'])
Out[17]: 0.013479040400098789
In [18]: frame['a'].corr(frame['b'], method='spearman')
Out[18]: -0.0072898851595406388
# Pairwise correlation of DataFrame columns
In [19]: frame.corr()
Out[19]:
a b c d e
a 1.000000 0.013479 -0.049269 -0.042239 -0.028525
b 0.013479 1.000000 -0.020433 -0.011139 0.005654
c -0.049269 -0.020433 1.000000 0.018587 -0.054269
d -0.042239 -0.011139 0.018587 1.000000 -0.017060
e -0.028525 0.005654 -0.054269 -0.017060 1.000000
Обратите внимание, что нечисловые столбцы будут автоматически исключены из расчёта корреляции.
Подобно cov, corr также поддерживает необязательное ключевое слово min_periods.
In [20]: frame = pd.DataFrame(np.random.randn(20, 3), columns=['a', 'b', 'c'])
In [21]: frame.ix[:5, 'a'] = np.nan
In [22]: frame.ix[5:10, 'b'] = np.nan
In [23]: frame.corr()
Out[23]:
a b c
a 1.000000 -0.076520 0.160092
b -0.076520 1.000000 0.135967
c 0.160092 0.135967 1.000000
In [24]: frame.corr(min_periods=12)
Out[24]:
a b c
a 1.000000 NaN 0.160092
b NaN 1.000000 0.135967
c 0.160092 0.135967 1.000000
Реализованный родственный метод corrwith применяется к DataFrame для вычисления корреляции между рядами с одинаковыми метками, содержащимися в разных объектах DataFrame.
In [25]: index = ['a', 'b', 'c', 'd', 'e'] In [26]: columns = ['one', 'two', 'three', 'four'] In [27]: df1 = pd.DataFrame(np.random.randn(5, 4), index=index, columns=columns) In [28]: df2 = pd.DataFrame(np.random.randn(4, 4), index=index[:4], columns=columns) In [29]: df1.corrwith(df2) Out[29]: one -0.125501 two -0.493244 three 0.344056 four 0.004183 dtype: float64 In [30]: df2.corrwith(df1, axis=1) Out[30]: a -0.675817 b 0.458296 c 0.190809 d -0.186275 e NaN dtype: float64
Ранжирование данных
Метод rank генерирует ранжирование данных, при этом одинаковые значения присваивают среднее значение рангов (по умолчанию) для группы:
In [31]: s = pd.Series(np.random.np.random.randn(5), index=list('abcde'))
In [32]: s['d'] = s['b'] # so there's a tie
In [33]: s.rank()
Out[33]:
a 5.0
b 2.5
c 1.0
d 2.5
e 4.0
dtype: float64
rank также является методом DataFrame и может ранжировать либо строки (axis=0), либо столбцы (axis=1). Значения NaN исключаются из ранжирования.
In [34]: df = pd.DataFrame(np.random.np.random.randn(10, 6))
In [35]: df[4] = df[2][:5] # some ties
In [36]: df
Out[36]:
0 1 2 3 4 5
0 -0.904948 -1.163537 -1.457187 0.135463 -1.457187 0.294650
1 -0.976288 -0.244652 -0.748406 -0.999601 -0.748406 -0.800809
2 0.401965 1.460840 1.256057 1.308127 1.256057 0.876004
3 0.205954 0.369552 -0.669304 0.038378 -0.669304 1.140296
4 -0.477586 -0.730705 -1.129149 -0.601463 -1.129149 -0.211196
5 -1.092970 -0.689246 0.908114 0.204848 NaN 0.463347
6 0.376892 0.959292 0.095572 -0.593740 NaN -0.069180
7 -1.002601 1.957794 -0.120708 0.094214 NaN -1.467422
8 -0.547231 0.664402 -0.519424 -0.073254 NaN -1.263544
9 -0.250277 -0.237428 -1.056443 0.419477 NaN 1.375064
In [37]: df.rank(1)
Out[37]:
0 1 2 3 4 5
0 4.0 3.0 1.5 5.0 1.5 6.0
1 2.0 6.0 4.5 1.0 4.5 3.0
2 1.0 6.0 3.5 5.0 3.5 2.0
3 4.0 5.0 1.5 3.0 1.5 6.0
4 5.0 3.0 1.5 4.0 1.5 6.0
5 1.0 2.0 5.0 3.0 NaN 4.0
6 4.0 5.0 3.0 1.0 NaN 2.0
7 2.0 5.0 3.0 4.0 NaN 1.0
8 2.0 5.0 3.0 4.0 NaN 1.0
9 2.0 3.0 1.0 4.0 NaN 5.0
rank необязательно принимает параметр ascending, который по умолчанию равен true; если он false, данные сортируются в обратном порядке, и более высоким значениям присваивается меньший ранг.
rank поддерживает различные методы разбиения при равенстве, задаваемые параметром method:
-
average: средний ранг связанной группы -
min: наименьший ранг в группе -
max: наибольший ранг в группе -
first: ранги назначаются в порядке их появления в массиве
Функции окна
Предупреждение
До версии 0.18.0 pd.rolling_*, pd.expanding_*, и pd.ewm* были функциями уровня модуля и теперь устарели. Они заменены использованием объектов Rolling, Expanding и EWM и соответствующего вызова метода.
Предупреждение об устаревании покажет новый синтаксис, см. пример здесь. Вы можете просмотреть предыдущую документацию здесь.
Для работы с данными предоставлено множество функций окон для вычисления распространенных статистик окна или скользящего среднего. К ним относятся подсчет, сумма, среднее значение, медиана, корреляция, дисперсия, ковариация, стандартное отклонение, асимметрия и эксцесс.
Примечание
API для статистик окон очень похож на работу с объектами GroupBy, см. документацию здесь.
Мы работаем с данными rolling, expanding и exponentially weighted через соответствующие объекты Rolling, Expanding и EWM.
In [38]: s = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2000', periods=1000))
In [39]: s = s.cumsum()
In [40]: s
Out[40]:
2000-01-01 -0.268824
2000-01-02 -1.771855
2000-01-03 -0.818003
2000-01-04 -0.659244
2000-01-05 -1.942133
2000-01-06 -1.869391
2000-01-07 0.563674
...
2002-09-20 -68.233054
2002-09-21 -66.765687
2002-09-22 -67.457323
2002-09-23 -69.253182
2002-09-24 -70.296818
2002-09-25 -70.844674
2002-09-26 -72.475016
Freq: D, dtype: float64
Они создаются из методов объектов Series и DataFrame.
In [41]: r = s.rolling(window=60) In [42]: r Out[42]: Rolling [window=60,center=False,axis=0]
Эти объекты обеспечивают автодополнение доступных методов и свойств.
In [14]: r. r.agg r.apply r.count r.exclusions r.max r.median r.name r.skew r.sum r.aggregate r.corr r.cov r.kurt r.mean r.min r.quantile r.std r.var
В целом, у этих методов одинаковый интерфейс. Все они принимают следующие аргументы:
-
window: размер скользящего окна -
min_periods: порог непустых значений данных для требования (в противном случае результат NA) -
center: булево, устанавливать метки в центре (по умолчанию False)
Предупреждение
Аргументы freq и how были в API до изменений 0.18.0. Они устарели в новом API. Можно просто перевыбрать входные данные перед созданием функции окна.
Например, вместо s.rolling(window=5,freq='D').max() для получения максимального значения в окне скользящего среднего 5 дней можно использовать s.resample('D').max().rolling(window=5).max(), что сначала перевыбирает данные до дневных данных, а затем предоставляет окно скользящего среднего 5 дней.
Затем мы можем вызвать методы этих объектов rolling. Они возвращают объекты с аналогичными индексами.
In [43]: r.mean()
Out[43]:
2000-01-01 NaN
2000-01-02 NaN
2000-01-03 NaN
2000-01-04 NaN
2000-01-05 NaN
2000-01-06 NaN
2000-01-07 NaN
...
2002-09-20 -62.694135
2002-09-21 -62.812190
2002-09-22 -62.914971
2002-09-23 -63.061867
2002-09-24 -63.213876
2002-09-25 -63.375074
2002-09-26 -63.539734
Freq: D, dtype: float64
In [44]: s.plot(style='k--') Out[44]: <matplotlib.axes._subplots.AxesSubplot at 0x11ce37110> In [45]: r.mean().plot(style='k') Out[45]: <matplotlib.axes._subplots.AxesSubplot at 0x11ce37110>
Они также могут применяться к объектам DataFrame. Это фактически просто синтаксический сахар для применения оператора скользящего окна ко всем столбцам DataFrame:
In [46]: df = pd.DataFrame(np.random.randn(1000, 4),
....: index=pd.date_range('1/1/2000', periods=1000),
....: columns=['A', 'B', 'C', 'D'])
....:
In [47]: df = df.cumsum()
In [48]: df.rolling(window=60).sum().plot(subplots=True)
Out[48]:
array([<matplotlib.axes._subplots.AxesSubplot object at 0x11cdc2890>,
<matplotlib.axes._subplots.AxesSubplot object at 0x120dfef50>,
<matplotlib.axes._subplots.AxesSubplot object at 0x120cd4110>,
<matplotlib.axes._subplots.AxesSubplot object at 0x1127f6e90>], dtype=object)
Краткое описание методов
Мы предоставляем ряд распространенных статистических функций:
| Метод | Описание |
|---|---|
count() | Количество непустых наблюдений |
sum() | Сумма значений |
mean() | Среднее значение значений |
median() | Арифметическая медиана значений |
min() | Минимальное значение |
max() | Максимальное значение |
std() | Выборочное стандартное отклонение (с поправкой на бесслововость) |
var() | Несмещённая дисперсия |
skew() | Выборочная асимметрия (третий момент) |
kurt() | Выборовый эксцесс (четвертый момент) |
quantile() | Выборочный квантиль (значение в %) |
apply() | Общее применение |
cov() | Несмещённая ковариация (бинарная) |
corr() | Корреляция (бинарная) |
Функция apply() принимает дополнительный аргумент func и выполняет общие вычисления скользящего среднего. Аргумент func должен быть единственной функцией, которая создаёт единственное значение из входного массива ndarray. Предположим, что мы хотели вычислить среднее абсолютное отклонение в скользящем режиме:
In [49]: mad = lambda x: np.fabs(x - x.mean()).mean() In [50]: s.rolling(window=60).apply(mad).plot(style='k') Out[50]: <matplotlib.axes._subplots.AxesSubplot at 0x112f25950>
Скользящие окна
Передача win_type в .rolling генерирует вычисление скользящего окна общего вида, взвешенное согласно win_type. Доступны следующие методы:
| Метод | Описание |
|---|---|
sum() | Сумма значений |
mean() | Среднее значение |
Веса, используемые в окне, задаются ключевым словом win_type. Список распознаваемых типов:
boxcartriangblackmanhammingbartlettparzenbohmanblackmanharrisnuttallbarthann-
kaiser(требуется beta) -
gaussian(требуется std) -
general_gaussian(требуется power, width) -
slepian(требуется width).
In [51]: ser = pd.Series(np.random.randn(10), index=pd.date_range('1/1/2000', periods=10))
In [52]: ser.rolling(window=5, win_type='triang').mean()
Out[52]:
2000-01-01 NaN
2000-01-02 NaN
2000-01-03 NaN
2000-01-04 NaN
2000-01-05 -1.037870
2000-01-06 -0.767705
2000-01-07 -0.383197
2000-01-08 -0.395513
2000-01-09 -0.558440
2000-01-10 -0.672416
Freq: D, dtype: float64
Обратите внимание, что окно boxcar эквивалентно mean().
In [53]: ser.rolling(window=5, win_type='boxcar').mean() Out[53]: 2000-01-01 NaN 2000-01-02 NaN 2000-01-03 NaN 2000-01-04 NaN 2000-01-05 -0.841164 2000-01-06 -0.779948 2000-01-07 -0.565487 2000-01-08 -0.502815 2000-01-09 -0.553755 2000-01-10 -0.472211 Freq: D, dtype: float64 In [54]: ser.rolling(window=5).mean() Out[54]: 2000-01-01 NaN 2000-01-02 NaN 2000-01-03 NaN 2000-01-04 NaN 2000-01-05 -0.841164 2000-01-06 -0.779948 2000-01-07 -0.565487 2000-01-08 -0.502815 2000-01-09 -0.553755 2000-01-10 -0.472211 Freq: D, dtype: float64
Для некоторых функций окон, необходимо указать дополнительные параметры:
In [55]: ser.rolling(window=5, win_type='gaussian').mean(std=0.1) Out[55]: 2000-01-01 NaN 2000-01-02 NaN 2000-01-03 NaN 2000-01-04 NaN 2000-01-05 -1.309989 2000-01-06 -1.153000 2000-01-07 0.606382 2000-01-08 -0.681101 2000-01-09 -0.289724 2000-01-10 -0.996632 Freq: D, dtype: float64
Примечание
Для .sum() с win_type, нормализация весов для окна не выполняется. Передача пользовательских весов [1, 1, 1] даст другой результат, чем передача весов [2, 2, 2], например. При передаче win_type вместо явного указания весов, веса уже нормализованы, так что максимальный вес равен 1.
В отличие от этого, характер вычисления .mean() таков, что веса нормализуются относительно друг друга. Веса [1, 1, 1] и [2, 2, 2] дают одинаковый результат.
Центрирование окон
По умолчанию метки устанавливаются на правом краю окна, но доступно ключевое слово center, чтобы метки можно было установить в центр.
In [56]: ser.rolling(window=5).mean() Out[56]: 2000-01-01 NaN 2000-01-02 NaN 2000-01-03 NaN 2000-01-04 NaN 2000-01-05 -0.841164 2000-01-06 -0.779948 2000-01-07 -0.565487 2000-01-08 -0.502815 2000-01-09 -0.553755 2000-01-10 -0.472211 Freq: D, dtype: float64 In [57]: ser.rolling(window=5, center=True).mean() Out[57]: 2000-01-01 NaN 2000-01-02 NaN 2000-01-03 -0.841164 2000-01-04 -0.779948 2000-01-05 -0.565487 2000-01-06 -0.502815 2000-01-07 -0.553755 2000-01-08 -0.472211 2000-01-09 NaN 2000-01-10 NaN Freq: D, dtype: float64
Двоичные функции окна
cov() и corr() могут вычислять статистику скользящего окна по двум Series или любой комбинации DataFrame/Series или DataFrame/DataFrame. Вот поведение в каждом случае:
- два
Series: вычислить статистику для сопряжения. -
DataFrame/Series: вычислить статистику для каждого столбца DataFrame с переданным Series, тем самым возвращая DataFrame. -
DataFrame/DataFrame: по умолчанию вычисляет статистику для соответствующих имен столбцов, возвращая DataFrame. Если передано ключевое словоpairwise=True, то вычисляет статистику для каждой пары столбцов, возвращаяPanel, чьиitemsявляются датами, о которых идет речь (см. следующий раздел).
Например:
In [58]: df2 = df[:20]
In [59]: df2.rolling(window=5).corr(df2['B'])
Out[59]:
A B C D
2000-01-01 NaN NaN NaN NaN
2000-01-02 NaN NaN NaN NaN
2000-01-03 NaN NaN NaN NaN
2000-01-04 NaN NaN NaN NaN
2000-01-05 -0.262853 1.0 0.334449 0.193380
2000-01-06 -0.083745 1.0 -0.521587 -0.556126
2000-01-07 -0.292940 1.0 -0.658532 -0.458128
... ... ... ... ...
2000-01-14 0.519499 1.0 -0.687277 0.192822
2000-01-15 0.048982 1.0 0.167669 -0.061463
2000-01-16 0.217190 1.0 0.167564 -0.326034
2000-01-17 0.641180 1.0 -0.164780 -0.111487
2000-01-18 0.130422 1.0 0.322833 0.632383
2000-01-19 0.317278 1.0 0.384528 0.813656
2000-01-20 0.293598 1.0 0.159538 0.742381
[20 rows x 4 columns]
Вычисление скользящих парных ковариаций и корреляций
В финансовом анализе и других областях часто приходится вычислять матрицы ковариации и корреляции для набора временных рядов. Зачастую также интересуют матрицы скользящей ковариации и корреляции. Это можно сделать, передав ключевое слово pairwise, которое в случае DataFrame входных данных вернёт Panel, чьи items являются датами, о которых идет речь. В случае единственного аргумента DataFrame аргумент pairwise можно даже опустить:
Примечание
Пропущенные значения игнорируются, и каждое значение вычисляется с использованием парных полных наблюдений. См. раздел «ковариация» здесь для предупреждений, связанных с этим методом вычисления матриц ковариации и корреляции.
In [60]: covs = df[['B','C','D']].rolling(window=50).cov(df[['A','B','C']], pairwise=True)
In [61]: covs[df.index[-50]]
Out[61]:
A B C
B 2.667506 1.671711 1.938634
C 8.513843 1.938634 10.556436
D -7.714737 -1.434529 -7.082653
In [62]: correls = df.rolling(window=50).corr()
In [63]: correls[df.index[-50]]
Out[63]:
A B C D
A 1.000000 0.604221 0.767429 -0.776170
B 0.604221 1.000000 0.461484 -0.381148
C 0.767429 0.461484 1.000000 -0.748863
D -0.776170 -0.381148 -0.748863 1.000000
Вы можете эффективно извлечь временной ряд корреляций между двумя столбцами, используя индексацию .loc:
In [64]: correls.loc[:, 'A', 'C'].plot() Out[64]: <matplotlib.axes._subplots.AxesSubplot at 0x11ea521d0>
Агрегирование
После создания объектов Rolling, Expanding или EWM, доступны несколько методов для выполнения нескольких вычислений над данными. Это очень похоже на агрегирование .groupby(...).agg , описанное здесь.
In [65]: dfa = pd.DataFrame(np.random.randn(1000, 3),
....: index=pd.date_range('1/1/2000', periods=1000),
....: columns=['A', 'B', 'C'])
....:
In [66]: r = dfa.rolling(window=60,min_periods=1)
In [67]: r
Out[67]: Rolling [window=60,min_periods=1,center=False,axis=0]
Мы можем агрегировать, передавая функцию всему DataFrame или выбирая Series (или несколько Series) с помощью стандартного getitem.
In [68]: r.aggregate(np.sum)
Out[68]:
A B C
2000-01-01 0.314226 -0.001675 0.071823
2000-01-02 1.206791 0.678918 -0.267817
2000-01-03 1.421701 0.600508 -0.445482
2000-01-04 1.912539 -0.759594 1.146974
2000-01-05 2.919639 -0.061759 -0.743617
2000-01-06 2.665637 1.298392 -0.803529
2000-01-07 2.513985 1.923089 -1.928308
... ... ... ...
2002-09-20 1.447669 -12.360302 2.734381
2002-09-21 1.871783 -13.896542 3.086102
2002-09-22 2.540658 -12.594402 3.162542
2002-09-23 2.974674 -12.727703 3.861005
2002-09-24 1.391366 -13.584590 3.790683
2002-09-25 2.027313 -15.083214 3.377896
2002-09-26 1.290363 -13.569459 3.809884
[1000 rows x 3 columns]
In [69]: r['A'].aggregate(np.sum)
Out[69]:
2000-01-01 0.314226
2000-01-02 1.206791
2000-01-03 1.421701
2000-01-04 1.912539
2000-01-05 2.919639
2000-01-06 2.665637
2000-01-07 2.513985
...
2002-09-20 1.447669
2002-09-21 1.871783
2002-09-22 2.540658
2002-09-23 2.974674
2002-09-24 1.391366
2002-09-25 2.027313
2002-09-26 1.290363
Freq: D, Name: A, dtype: float64
In [70]: r[['A','B']].aggregate(np.sum)
Out[70]:
A B
2000-01-01 0.314226 -0.001675
2000-01-02 1.206791 0.678918
2000-01-03 1.421701 0.600508
2000-01-04 1.912539 -0.759594
2000-01-05 2.919639 -0.061759
2000-01-06 2.665637 1.298392
2000-01-07 2.513985 1.923089
... ... ...
2002-09-20 1.447669 -12.360302
2002-09-21 1.871783 -13.896542
2002-09-22 2.540658 -12.594402
2002-09-23 2.974674 -12.727703
2002-09-24 1.391366 -13.584590
2002-09-25 2.027313 -15.083214
2002-09-26 1.290363 -13.569459
[1000 rows x 2 columns]
Как вы видите, результат агрегирования будет содержать выбранные столбцы или все столбцы, если они не выбраны.
Применение нескольких функций одновременно
В случае оконных Series вы также можете передать список или словарь функций для агрегирования, что выведет DataFrame:
In [71]: r['A'].agg([np.sum, np.mean, np.std])
Out[71]:
sum mean std
2000-01-01 0.314226 0.314226 NaN
2000-01-02 1.206791 0.603396 0.408948
2000-01-03 1.421701 0.473900 0.365959
2000-01-04 1.912539 0.478135 0.298925
2000-01-05 2.919639 0.583928 0.350682
2000-01-06 2.665637 0.444273 0.464115
2000-01-07 2.513985 0.359141 0.479828
... ... ... ...
2002-09-20 1.447669 0.024128 1.034827
2002-09-21 1.871783 0.031196 1.031417
2002-09-22 2.540658 0.042344 1.026341
2002-09-23 2.974674 0.049578 1.030021
2002-09-24 1.391366 0.023189 1.024793
2002-09-25 2.027313 0.033789 1.022099
2002-09-26 1.290363 0.021506 1.024751
[1000 rows x 3 columns]
Если передаётся словарь, ключи будут использоваться для именования столбцов. В противном случае будет использоваться имя функции (сохранённое в объекте функции).
In [72]: r['A'].agg({'result1' : np.sum,
....: 'result2' : np.mean})
....:
Out[72]:
result2 result1
2000-01-01 0.314226 0.314226
2000-01-02 0.603396 1.206791
2000-01-03 0.473900 1.421701
2000-01-04 0.478135 1.912539
2000-01-05 0.583928 2.919639
2000-01-06 0.444273 2.665637
2000-01-07 0.359141 2.513985
... ... ...
2002-09-20 0.024128 1.447669
2002-09-21 0.031196 1.871783
2002-09-22 0.042344 2.540658
2002-09-23 0.049578 2.974674
2002-09-24 0.023189 1.391366
2002-09-25 0.033789 2.027313
2002-09-26 0.021506 1.290363
[1000 rows x 2 columns]
В случае оконного DataFrame вы можете передать список функций, применяемых к каждому столбцу, что даёт агрегированный результат с иерархическим индексом:
In [73]: r.agg([np.sum, np.mean])
Out[73]:
A B C
sum mean sum mean sum mean
2000-01-01 0.314226 0.314226 -0.001675 -0.001675 0.071823 0.071823
2000-01-02 1.206791 0.603396 0.678918 0.339459 -0.267817 -0.133908
2000-01-03 1.421701 0.473900 0.600508 0.200169 -0.445482 -0.148494
2000-01-04 1.912539 0.478135 -0.759594 -0.189899 1.146974 0.286744
2000-01-05 2.919639 0.583928 -0.061759 -0.012352 -0.743617 -0.148723
2000-01-06 2.665637 0.444273 1.298392 0.216399 -0.803529 -0.133921
2000-01-07 2.513985 0.359141 1.923089 0.274727 -1.928308 -0.275473
... ... ... ... ... ... ...
2002-09-20 1.447669 0.024128 -12.360302 -0.206005 2.734381 0.045573
2002-09-21 1.871783 0.031196 -13.896542 -0.231609 3.086102 0.051435
2002-09-22 2.540658 0.042344 -12.594402 -0.209907 3.162542 0.052709
2002-09-23 2.974674 0.049578 -12.727703 -0.212128 3.861005 0.064350
2002-09-24 1.391366 0.023189 -13.584590 -0.226410 3.790683 0.063178
2002-09-25 2.027313 0.033789 -15.083214 -0.251387 3.377896 0.056298
2002-09-26 1.290363 0.021506 -13.569459 -0.226158 3.809884 0.063498
[1000 rows x 6 columns]
Передача словаря функций по умолчанию имеет другое поведение, см. следующий раздел.
Применение разных функций к столбцам DataFrame
Передав словарь в aggregate, вы можете применить разную агрегацию к столбцам DataFrame:
In [74]: r.agg({'A' : np.sum,
....: 'B' : lambda x: np.std(x, ddof=1)})
....:
Out[74]:
A B
2000-01-01 0.314226 NaN
2000-01-02 1.206791 0.482437
2000-01-03 1.421701 0.417825
2000-01-04 1.912539 0.851468
2000-01-05 2.919639 0.837474
2000-01-06 2.665637 0.935441
2000-01-07 2.513985 0.867770
... ... ...
2002-09-20 1.447669 1.084259
2002-09-21 1.871783 1.088368
2002-09-22 2.540658 1.084707
2002-09-23 2.974674 1.084936
2002-09-24 1.391366 1.079268
2002-09-25 2.027313 1.091334
2002-09-26 1.290363 1.060255
[1000 rows x 2 columns]
Имена функций также могут быть строками. Для того, чтобы строка была допустимой, она должна быть реализована в объекте окна.
In [75]: r.agg({'A' : 'sum', 'B' : 'std'})
Out[75]:
A B
2000-01-01 0.314226 NaN
2000-01-02 1.206791 0.482437
2000-01-03 1.421701 0.417825
2000-01-04 1.912539 0.851468
2000-01-05 2.919639 0.837474
2000-01-06 2.665637 0.935441
2000-01-07 2.513985 0.867770
... ... ...
2002-09-20 1.447669 1.084259
2002-09-21 1.871783 1.088368
2002-09-22 2.540658 1.084707
2002-09-23 2.974674 1.084936
2002-09-24 1.391366 1.079268
2002-09-25 2.027313 1.091334
2002-09-26 1.290363 1.060255
[1000 rows x 2 columns]
Кроме того, вы можете передать вложенный словарь, чтобы указать различные агрегации для разных столбцов.
In [76]: r.agg({'A' : ['sum','std'], 'B' : ['mean','std'] })
Out[76]:
A B
sum std mean std
2000-01-01 0.314226 NaN -0.001675 NaN
2000-01-02 1.206791 0.408948 0.339459 0.482437
2000-01-03 1.421701 0.365959 0.200169 0.417825
2000-01-04 1.912539 0.298925 -0.189899 0.851468
2000-01-05 2.919639 0.350682 -0.012352 0.837474
2000-01-06 2.665637 0.464115 0.216399 0.935441
2000-01-07 2.513985 0.479828 0.274727 0.867770
... ... ... ... ...
2002-09-20 1.447669 1.034827 -0.206005 1.084259
2002-09-21 1.871783 1.031417 -0.231609 1.088368
2002-09-22 2.540658 1.026341 -0.209907 1.084707
2002-09-23 2.974674 1.030021 -0.212128 1.084936
2002-09-24 1.391366 1.024793 -0.226410 1.079268
2002-09-25 2.027313 1.022099 -0.251387 1.091334
2002-09-26 1.290363 1.024751 -0.226158 1.060255
[1000 rows x 4 columns]
Расширяющие окна
Альтернативой скользящей статистике является использование расширяющегося окна, которое даёт значение статистики со всеми доступными данными до этого момента времени.
Они следуют аналогичному интерфейсу .rolling, причём метод .expanding возвращает объект Expanding.
Поскольку эти вычисления являются частным случаем скользящей статистики, они реализованы в pandas таким образом, что следующие два вызова эквивалентны:
In [77]: df.rolling(window=len(df), min_periods=1).mean()[:5]
Out[77]:
A B C D
2000-01-01 -1.388345 3.317290 0.344542 -0.036968
2000-01-02 -1.123132 3.622300 1.675867 0.595300
2000-01-03 -0.628502 3.626503 2.455240 1.060158
2000-01-04 -0.768740 3.888917 2.451354 1.281874
2000-01-05 -0.824034 4.108035 2.556112 1.140723
In [78]: df.expanding(min_periods=1).mean()[:5]
Out[78]:
A B C D
2000-01-01 -1.388345 3.317290 0.344542 -0.036968
2000-01-02 -1.123132 3.622300 1.675867 0.595300
2000-01-03 -0.628502 3.626503 2.455240 1.060158
2000-01-04 -0.768740 3.888917 2.451354 1.281874
2000-01-05 -0.824034 4.108035 2.556112 1.140723
У них есть аналогичный набор методов .rolling методов.
Краткое описание методов
| Функция | Описание |
|---|---|
count() | Количество ненулевых наблюдений |
sum() | Сумма значений |
mean() | Среднее значение |
median() | Арифметическая медиана значений |
min() | Минимальное значение |
max() | Максимальное значение |
std() | Несмещенное стандартное отклонение |
var() | Несмещенная дисперсия |
skew() | Несмещенная асимметрия (3-й момент) |
kurt() | Несмещенная эксцесс (4-й момент) |
quantile() | Выборочная квантиль (значение в %) |
apply() | Общее применение |
cov() | Несмещенная ковариация (бинарная) |
corr() | Корреляция (бинарная) |
Помимо отсутствия параметра window, эти функции имеют такие же интерфейсы, как их .rolling аналоги. Как и выше, все они принимают следующие параметры:
-
min_periods: порог количества ненулевых точек данных, необходимых для вычисления статистики. По умолчанию используется минимальное количество, необходимое для вычисления статистики. ЗначениеNaNsне будет выведено, как только будет встреченоmin_periodsненулевых точек данных. -
center: булево значение, указывающее, нужно ли размещать метки в центре (по умолчанию False)
Примечание
Методы .rolling и .expanding не возвращают значение NaN, если в текущем окне присутствует не менее min_periods ненулевых значений. Это отличается от cumsum, cumprod, cummax, и cummin, которые возвращают NaN в выводе всякий раз, когда встречается NaN в вводе.
Статистика с расширяющимся окном будет более стабильной (и менее отзывчивой), чем её аналог с окном скользящего среднего, поскольку увеличение размера окна уменьшает относительное влияние отдельной точки данных. В качестве примера, вот результат mean() для предыдущего временного ряда данных:
In [79]: s.plot(style='k--') Out[79]: <matplotlib.axes._subplots.AxesSubplot at 0x118390f10> In [80]: s.expanding().mean().plot(style='k') Out[80]: <matplotlib.axes._subplots.AxesSubplot at 0x118390f10>
Экспоненциально взвешенные окна
Связанный набор функций представляет собой экспоненциально взвешенные версии нескольких вышеперечисленных статистик. Аналогичный интерфейс .rolling и .expanding достигается через метод .ewm для получения объекта EWM. Предоставлено несколько методов расширения EW (экспоненциально взвешенных):
| Функция | Описание |
|---|---|
mean() | EW скользящее среднее |
var() | EW скользящая дисперсия |
std() | EW скользящее стандартное отклонение |
corr() | EW скользящая корреляция |
cov() | EW скользящая ковариация |
В общем случае взвешенное скользящее среднее вычисляется как
где — входные данные, а
— результат.
Функции EW поддерживают два варианта экспоненциальных весов. По умолчанию, adjust=True, используются веса , что дает
Когда adjust=False указано, скользящие средние вычисляются как
что эквивалентно использованию весов
Примечание
Эти уравнения иногда записываются с использованием , например:
Различие между вышеуказанными двумя вариантами возникает потому, что мы имеем дело с рядами, которые имеют конечную историю. Рассмотрим ряд бесконечной истории:
Заметим, что знаменатель представляет собой геометрическую прогрессию с начальным членом, равным 1, и отношением , что дает
что показывает эквивалентность вышеуказанных двух вариантов для бесконечных рядов. При adjust=True получаем , и из последнего представления выше мы получаем
, следовательно, предполагается, что
— это не обычное значение, а экспоненциально взвешенное значение момента бесконечного ряда до этого момента.
Должно быть выполнено условие , и хотя с версии 0.18.0 можно непосредственно передавать
, зачастую проще использовать диапазон, центр масс (com) или период полураспада для экспоненциально взвешенного момента:
Для функций EW необходимо указать ровно один из диапазона, центра масс, периода полураспада и альфа:
- Диапазон соответствует тому, что обычно называют «EW скользящим средним за N дней».
-
Центр масс имеет более физическое толкование и может быть представлен в терминах диапазона:
.
- Период полураспада — это период времени, в течение которого экспоненциальный вес уменьшается до половины.
- Альфа непосредственно задаёт коэффициент сглаживания.
Вот пример для одномерного временного ряда:
In [81]: s.plot(style='k--') Out[81]: <matplotlib.axes._subplots.AxesSubplot at 0x1132e2dd0> In [82]: s.ewm(span=20).mean().plot(style='k') Out[82]: <matplotlib.axes._subplots.AxesSubplot at 0x1132e2dd0>
EWM имеет аргумент min_periods, который имеет то же значение, что и во всех методах .expanding и .rolling: значения вывода не будут устанавливаться, пока не будет встречено не менее min_periods ненулевых значений в (расширяющемся) окне. (Это изменение по сравнению с версиями до 0.15.0, в которых аргумент min_periods влиял только на min_periods последовательные записи, начиная с первого ненулевого значения.)
EWM также имеет аргумент ignore_na, который определяет, как промежуточные нулевые значения влияют на вычисление весов. При значении ignore_na=False (по умолчанию) веса вычисляются на основе абсолютных позиций, так что промежуточные нулевые значения влияют на результат. При значении ignore_na=True (что воспроизводит поведение в версиях до 0.15.0), веса вычисляются, игнорируя промежуточные нулевые значения. Например, предполагая adjust=True, если ignore_na=False, взвешенное среднее значение 3, NaN, 5 вычисляется как
В то время как если ignore_na=True, взвешенное среднее значение вычисляется как
Функции var(), std(), и cov() имеют аргумент bias, определяющий, должны ли результаты содержать смещённые или несмещённые статистики. Например, если bias=True, ewmvar(x) вычисляется как ewmvar(x) = ewma(x**2) - ewma(x)**2; в то время как при значении bias=False (по умолчанию), смещённые статистические показатели дисперсии масштабируются с помощью корректирующих факторов
(Для , это сводится к обычному множителю
с
.) См. Взвешенная выборочная дисперсия для получения дополнительной информации.
© 2008–2012, AQR Capital Management, LLC, Lambda Foundry, Inc. and PyData Development Team
Licensed under the 3-clause BSD License.
https://pandas.pydata.org/pandas-docs/version/0.18.1/computation.html