Computational tools¶
このページでは python / pandas に付属している計算ツール関連の内容をまとめていきます. pandas での計算は基本的に横に強く,縦に弱い印象があります. つまり,カラムごとの処理は groupby 関数で大体うまく行くわけですが, 一行前とか,前後数行というのは少し悩みます.
このページで記述するのは上記のような ** 縦の処理 ** に関する記述です.
Percent Change: 変化高を求める¶
まずは単純に前のデータとの差分を考えてみます. 適当にランダムな一行データを作成します.
import pandas as pd
import numpy as np
ser = pd.Series(np.random.randn(8))
ser
ランダムな結果ですので値は毎回変わります. イメージをつかみやすいように私が試した際の結果を示しておきます.
ID | Values |
---|---|
0 | -2.395369 |
1 | 1.394761 |
2 | -0.682853 |
3 | 0.078911 |
4 | -0.865840 |
5 | -1.503717 |
6 | 0.575142 |
7 | 1.485806 |
さてこのデータの前との差分を求めるには pct_change 関数を使用します
ser.pct_change()
ID | Values |
---|---|
0 | NaN |
1 | -1.582274 |
2 | -1.489584 |
3 | -1.115561 |
4 | -11.972348 |
5 | 0.736714 |
6 | -1.382481 |
7 | 1.583371 |
ここで periods を指定するといくつ前までを使用するのかを指定できます. なお,DataFrame にも適応できます.
df = pd.DataFrame(np.random.randn(10, 4))
df.pct_change(periods=3)
Covariance, Correlation¶
続いては2つのデータの共分散を求める場合です.
s1 = pd.Series(np.random.randn(1000))
s2 = pd.Series(np.random.randn(1000))
s1.cov(s2)
Series に対して Series を適応させていることに注意してください.
ちなみに DataFrame に対してこの関数を使用すると 各カラム同士の共分散が求まります.
frame = pd.DataFrame(np.random.randn(1000, 5), columns=['a', 'b', 'c', 'd', 'e'])
frame.cov()
一方で相関を求めるには corr 関数を使用します.
frame.corr()
Moving (rolling) statistics / moments¶
で,このページの本題です. 特に信号処理系のデータを扱っていると, 移動平均のように,各データの前何フレームかを取得して平均をとったり,その他色々することがあるかと思います. このような場合のために pandas では rolling 系の関数がいくつか用意されています.
Function | Description |
---|---|
rolling_count | 対象の null 以外の数 |
rolling_sum | 総和 |
rolling_mean | 平均 |
rolling_median | メディアン |
rolling_min | 最小値 |
rolling_max | 最大値 |
rolling_std | 標準偏差 |
rolling_var | 分散 |
rolling_skew | 歪度 (3rd moment) |
rolling_kurt | 尖度 (4th moment) |
rolling_quantile | クオンタイル |
rolling_apply | 一般化 |
rolling_cov | 共分散 |
rolling_corr | 相関 |
rolling_window | 窓関数 |
例えば rolling_mean を例に説明すると以下のように使用します.
ts = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2000', periods=1000))
pd.rolling_mean(ts, 60)
ここで第二引数にはフレーム長を指定します.
ここで自作関数を当てはめたい場合, rolling_apply を使用します. 例えば以下のような感じです.
mad = lambda x: np.fabs(x - x.mean()).mean()
pd.rolling_apply(ts, 60, mad).plot(style='k')
注釈
複数の引数を受け取る場合は?
rolling_apply は基本的に一つのカラムに対する処理を前提にしています. しかし場合によっては複数のカラムを組み合わせた場合の処理を記述したい時もあります. 例えば,時系列データを使用していて時間ごとの傾き(単回帰の回帰係数)を取得したい時などです このような場合,一旦 apply 側に DataFrame のインデックスを渡してしまうことで 対処可能です.
- ここでは TIME, Value というカラムを持つ DataFrame を前提にしています.
from numpy import arange
from scipy.stats import linregress
from pandas import rolling_apply
def splope(idx):
now = df.iloc[idx]
return linregress(now['TIME'], now['Value'])[0]
df['slope'] = rolling_apply(arange(len(df)), 60, splope)