Computational tools

Last Change: 09-Sep-2015.
author : qh73xe

このページでは 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 系の関数がいくつか用意されています.

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)