1. ホーム
  2. python

[解決済み】python + NumPy / SciPyを使用してローリング/移動平均を計算する方法は?

2022-01-25 16:03:23

質問

numpy/scipyには単純に移動平均を計算する関数がないようで、以下のようなことが起こります。 複雑な解決策 .

私の疑問は2つあります。

  • numpyで移動平均を(正しく)実装する最も簡単な方法は何ですか?
  • これは自明ではなく、エラーが起こりやすいと思われるので 電池込み この場合は?

解決方法は?

これを実現する簡単な方法として np.convolve. を活用することです。 離散コンボリューション が計算され、それを使って ローリング平均 . の列で畳み込むことによって行うことができる. np.ones を、希望するスライディングウィンドウの長さと同じ長さにする。

そのために、次のような関数を定義することができる。

def moving_average(x, w):
    return np.convolve(x, np.ones(w), 'valid') / w

この関数は、シーケンス x と、長さが1であるものの列 w. ただし、選択された modevalid


x = np.array([5,3,8,10,2,1,5,1,0,2])

2

moving_average(x, 2) # array([4. , 5.5, 9. , 6. , 1.5, 3. , 3. , 0.5, 1. ])

4

moving_average(x, 4) # array([6.5 , 5.75, 5.25, 4.5 , 2.25, 1.75, 2. ])

convolve

どのように {コード は働くのか?

離散畳み込みがどのように計算されているか、もう少し詳しく見てみましょう。 次の関数は、以下のような方法を再現することを目的としています。 np.convolve が出力値を計算しています。

def mov_avg(x, w):
    for m in range(len(x)-(w-1)):
        yield sum(np.ones(w) * x[m:m+w]) / w 

上記の同じ例では、次のようになります。

list(mov_avg(x, 2))
# [4.0, 5.5, 9.0, 6.0, 1.5, 3.0, 3.0, 0.5, 1.0]

つまり、各ステップで行われているのは、1の配列と現在の ウィンドウ . この場合 np.ones(w)

sum

w=4

[1,1,1,1] [5,3,8,10,2,1,5,1,0,2] = (1*5 + 1*3 + 1*8 + 1*10) / w = 6.5

  [1,1,1,1]
[5,3,8,10,2,1,5,1,0,2]
= (1*3 + 1*8 + 1*10 + 1*2) / w = 5.75

というように、すべてのオーバーラップが実行されると、シーケンスの移動平均が返されます。