Translate

【超初心者向け】pythonでとりあえず手っ取り速くデータを補間・リサンプリングする方【補間】

pythonデータを扱ったりしていると、いろんなサンプリング周波数のデータを同時に計測することがありますよね。

何らかの方法で、データ計測開始時点をそろえたとして、サンプリングがそろっていないことには、データを並べたり、グラフで可視化する際にもとても面倒です。

そういった場合に必要な処理になるのが、補間もしくはリサンプリングといった処理プロセスになります。

この補間やリサンプリングはいろんな機械を使ってpythonでデータを扱う以上必須のテクニックになるので、覚えておいて損はありません。pythonでのコード自体は簡単なのですが、使う回数が頻回なので、いっそ関数化させてしまっても良いでしょう。

今回は、データの補間・リサンプリングをする処理を書いたpythonスクリプト作成し、関数化するところまでやってみることとしましょう(あくまでも甘味自身の覚え書きみたいなものです)。

当然初心者の甘味が書いているので、ミスとか無駄なコードの部分とかが多くあるかもしれませんが、そこはご了承していただけると幸いです。


補間するデータをまずは用意(今回はサンプルの適当な配列データ)

pythonで補間・リサンプリングするにあたって、いきなり関数のコードを載せてもいいのですが、今回は実際にデータがある方がわかりやすいと思うので、サンプルのデータを用意します。

補間・リサンプリング用にExcelで適当に作った意味のない配列を今回は二つ用意しました。

一つ目のデータは60行一列のデータ、二つ目のデータは100行一列のデータです。想定は60Hzと100Hzのサンプリング数の機器でとった二つのデータを補間・リサンプリングしてそろえるといった想定で行きましょう。

まずはデータの読み込み。今回test1.csv、test2.csvのデータを読み込みます。

#必要なパッケージのインポート
import numpy as np
import matplotlib.pyplot as plt
data1 = np.loadtxt('test1.csv',delimiter =',')
data2 = np.loadtxt('test2.csv',delimiter =',')

plt.plot(data1)
plt.plot(data2)



とりあえずデータをmatplotlibでグラフ描写し、データの雰囲気を確認してみましょう。
当然ですが、これら二つのデータの行数が異なるので、同じグラフに描画するとこんな感じで青色が途中で切れているような感じのデータになります。横軸をもし仮に時間として、このデータが、同じ現象を二つの異なる機器で同時に計測したものであったのであれば違和感がありますよね。

こういった場合に使うのが、補間・リサンプリングといった感じになります。

補間・リサンプリングには、scipyのinterp1dを使う。

では実際に補間・リサンプリングの処理をするコードを書いていってみましょう。今回は普段pythonで使っているnumpyに加えてscipyといったモジュールを使用していきます。scipyはこれまでに、バダーワースフィルタとかを作るときとかにも使ったツールになります。

その中の、interp1dという線形回帰のモジュールを使用します。以下コードになります。すでに関数化までしてしまっています。def~return○○までの部分をそのままコピペして貼り付けてresample()のカッコ内に必要なデータを入れ込んでやればとりあえず動くと思います。

#必要なパッケージのインポート
import numpy as np 
import matplotlib.pyplot as plt
from scipy.interpolate import interp1d
#必要になるscipyモジュールのインポート

#関数化した補間・リサンプルリングのコード
def resample(num,data,t0,tf):
    #numがリサンプリング後のデータ数
    #dataがリサンプルしたい生データ
    #t0は基本1を入力
    #tfはリサンプル前のデータのデータ数
    time_frame = np.arange(t0,tf+1,1)
    data = np.ndarray.flatten(data)
    f = interp1d(time_frame,data,kind= 'linear')
    t_resample = np.linspace(t0,tf,num)
    resamp_data = f(t_resample)
    return resamp_data


data1 = np.loadtxt('test1.csv',delimiter =',')
data2 = np.loadtxt('test2.csv',delimiter =',')

plt.plot(data1,label='data1')
plt.plot(data2,label='data2')

data_resample= resample(len(data2),data1,1,len(data1))
#len()は配列のデータの長さを取得する関数(言い換えるなら行数)

plt.plot(data_resample,label='resample(data1)')
plt.legend(loc = 'best')



グラフ化してみるとこんな感じです。確かにdata1のデータ(60Hz)のデータが100個のデータになっていますね。


pythonコードの行数自体は5行くらいで、一つのデータを補間・リサンプリングする程度であれば、べた書きでいいと思うのですが、補間・リサンプリングの場合には後述の理由から関数化した方が圧倒的に使いやすいです。


ざっとpythonで関数化までして書くとこんな感じです。補間・リサンプリングで気を付けないといけないのは、これは一列複数行のデータしか扱えないという点があります。なのでもし生データが複数列複数行のようなデータの場合には、事前に一列のデータにしておく必要があります。

なので多次元配列のデータを一度ぶち込んで一気にリサンプルすることができないので、べた書きだとその分行がどんどん増えていってしまうといったことになるので、関数化をおすすめします。