web-dev-qa-db-ja.com

1D numpy配列をダウンサンプリングする

ダウンサンプリングしたい1次元のnumpy配列があります。ダウンサンプリングラスターがデータに完全に適合しない場合は、次のいずれかの方法を使用できます。

  • ダウンサンプル間隔のオーバーラップ
  • 最後に残っている値の数に関係なく、別のダウンサンプリングされた値に変換する
  • ラスターに合わせて補間

基本的に私が持っている場合

1 2 6 2 1

そして、私は3倍にダウンサンプリングしていますが、以下のすべては問題ありません。

3 3

3 1.5

または、ここで補間によって与えられるものは何でも。

私はこれを行うための最速/最も簡単な方法を探しています。

見つけた scipy.signal.decimate 、しかしそれはそのように聞こえますdecimates値(必要に応じてそれらを取り出し、Xに1つだけ残します)。 scipy.signal.resample は正しい名前を持っているようですが、説明の中でフーリエ全体がどこにあるのかわかりません。私の信号は特に周期的ではありません。

ここで手を貸してくれませんか?これは本当に簡単な作業のようですが、これらの機能はすべて非常に複雑です...

21
TheChymera

配列のサイズがダウンサンプリング係数(R)で割り切れる単純なケースでは、配列をreshapeして、新しい軸に沿って平均を取ることができます。

import numpy as np
a = np.array([1.,2,6,2,1,7])
R = 3
a.reshape(-1, R)
=> array([[ 1.,  2.,  6.],
         [ 2.,  1.,  7.]])

a.reshape(-1, R).mean(axis=1)
=> array([ 3.        ,  3.33333333])

一般的なケースでは、NaNsで割り切れるサイズになるようにRsで配列をパディングし、scipy.nanmeanを使用して平均を取ることができます。

import math, scipy
b = np.append(a, [ 4 ])
b.shape
=> (7,)
pad_size = math.ceil(float(b.size)/R)*R - b.size
b_padded = np.append(b, np.zeros(pad_size)*np.NaN)
b_padded.shape
=> (9,)
scipy.nanmean(b_padded.reshape(-1,R), axis=1)
=> array([ 3.        ,  3.33333333,  4.])
28
shx2

ここでは、線形補間またはフーリエ法のいずれかを使用するいくつかのアプローチを示します。これらのメソッドは、アップサンプリングとダウンサンプリングをサポートしています。

import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import resample
from scipy.interpolate import interp1d

def ResampleLinear1D(original, targetLen):
    original = np.array(original, dtype=np.float)
    index_arr = np.linspace(0, len(original)-1, num=targetLen, dtype=np.float)
    index_floor = np.array(index_arr, dtype=np.int) #Round down
    index_ceil = index_floor + 1
    index_rem = index_arr - index_floor #Remain

    val1 = original[index_floor]
    val2 = original[index_ceil % len(original)]
    interp = val1 * (1.0-index_rem) + val2 * index_rem
    assert(len(interp) == targetLen)
    return interp

if __name__=="__main__":

    original = np.sin(np.arange(256)/10.0)
    targetLen = 100

    # Method 1: Use scipy interp1d (linear interpolation)
    # This is the simplest conceptually as it just uses linear interpolation. Scipy
    # also offers a range of other interpolation methods.
    f = interp1d(np.arange(256), original, 'linear')
    plt.plot(np.apply_along_axis(f, 0, np.linspace(0, 255, num=targetLen)))

    # Method 2: Use numpy to do linear interpolation
    # If you don't have scipy, you can do it in numpy with the above function
    plt.plot(ResampleLinear1D(original, targetLen))

    # Method 3: Use scipy's resample
    # Converts the signal to frequency space (Fourier method), then back. This
    # works efficiently on periodic functions but poorly on non-periodic functions.
    plt.plot(resample(original, targetLen))

    plt.show()
0
TimSC

配列のサイズがダウンサンプリング係数(R)で割り切れない場合、配列の再形成(分割)は、np.linspaceを使用し、その後に各サブ配列の平均を使用して実行できます。

input_arr = np.arange(531)

R = 150 (number of split)

split_arr = np.linspace(0, len(input_arr), num=R+1, dtype=int)

dwnsmpl_subarr = np.split(input_arr, split_arr[1:])

dwnsmpl_arr = np.array( list( np.mean(item) for item in dwnsmpl_subarr[:-1] ) )
0
Manoj Singh