Python
pandas
時系列
補間
リサンプリング

多次元時系列データをリサンプリング

はじめに

時系列データを扱っていると、
 ・データが一様な時間間隔でサンプリングされていない
 ・しかも多次元データ
な場合があります。
一様にサンプリングされていない多次元データを、任意のサンプリングレートで一気にリサンプリングする関数を作成しました。

開発環境
Python 3.5.2 Anaconda 4.2.0 (x86_64)
Mac OS X EI Capitan 10.11.6

まず時系列データを生成

multidim_interpolate.py
# coding: UTF-8

#各種必要なライブラリをインポート
import pandas as pd
import numpy as np
from datetime import datetime
from scipy import signal, interpolate
import matplotlib.pyplot as plt

collist=["cos","sin","tan"]
df = pd.DataFrame([np.zeros(3)],columns=collist,index=[0])
starttime = datetime.now()
for i in range(1000):
    elapsed = (datetime.now() - starttime).total_seconds()
    sin_df = pd.DataFrame({"sin" : np.sin(elapsed)},index = [elapsed])
    df =  df.append(sin_df)
    elapsed = (datetime.now() - starttime).total_seconds()
    cos_df = pd.DataFrame({"cos" : np.cos(elapsed)},index = [elapsed])
    df = df.append(cos_df)
    elapsed = (datetime.now() - starttime).total_seconds()
    tan_df = pd.DataFrame({"tan" : np.tan(elapsed)},index = [elapsed])
    df = df.append(tan_df)  

今回はsin,cos,tanの3次元のデータを取り扱うこととしています。また、各データのタイムスタンプを、pandas.DataFrame()のindexとして保持しています。

多次元時系列データをリサンプリングする関数

def multidim_resample(df, Hz=100):
    resample_df = pd.DataFrame()
    for col in df.columns:
        tmp_df = df[col].dropna()
        #補間とリサンプリング
        f = interpolate.interp1d(tmp_df.index,tmp_df)
        resample_x = np.arange(tmp_df.index.min(),tmp_df.index.max(),1/Hz)
        resample_y = f(resample_x)
        #リサンプリングした結果をresample_dfに保存
        resample_y= pd.DataFrame(resample_y, index=[resample_x],columns=[col])
        resample_df = pd.concat([resample_df, resample_y], axis=1)
    resample_df = resample_df.dropna()
    return resample_df

各列を順番にリサンプリングし、最後にconcatしています。
今回は線形補間として、

f = interpolate.interp1d(tmp_df.index,tmp_df)

としましたが、引数を色々と変えることで、スプライン補間やらなんやらも使えるようです。
scipy.interpolate.interp1d

使ってみる

resample_df = multidim_resample(df,100)
resample_df.plot(ylim=[-1, 1])
plt.show()

resample_df.png

いい感じで補間されたっぽいです。

まとめ

一様にサンプリングされていない多次元データを、任意のサンプリングレートで一気にリサンプリングする関数を作成しました。
サンプリングレートが1秒とかなら、pandas.DataFrame.resampleで一気にやっちゃうのが楽ですね。