wake-up-neo.com

Downloaden Sie ein 1D-numpy-Array

Ich habe ein 1-d-numpy-Array, das ich gerne herunterrechnen möchte. Eine der folgenden Methoden ist zulässig, wenn das Downsampling-Raster nicht perfekt zu den Daten passt:

  • überlappen die Abtastintervalle
  • konvertiere die verbleibende Anzahl von Werten am Ende in einen separaten unterabgetasteten Wert
  • interpolieren, um das Raster anzupassen

im Grunde, wenn ich habe 

1 2 6 2 1

und ich bin mit dem Faktor 3 nachuntersuchend. Alle folgenden Punkte sind in Ordnung:

3 3

3 1.5

oder was auch immer eine Interpolation mir hier geben würde.

Ich suche nur den schnellsten/einfachsten Weg, dies zu tun.

Ich habe scipy.signal.decimate gefunden, aber das klingt wie dezimiert die Werte (nimmt sie je nach Bedarf heraus und hinterlässt nur einen Wert in X). scipy.signal.resample scheint den richtigen Namen zu haben, aber ich verstehe nicht, wohin die ganze Fourier-Sache in der Beschreibung geht. Mein Signal ist nicht besonders periodisch.

Könntest du mir hier helfen? Dies scheint eine sehr einfache Aufgabe zu sein, aber alle diese Funktionen sind ziemlich kompliziert ...

18
TheChymera

In dem einfachen Fall, in dem die Größe Ihres Arrays durch den Downsampling-Faktor (R) teilbar ist, können Sie reshape Ihr Array verwenden und den Mittelwert entlang der neuen Achse nehmen:

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])

Im Allgemeinen können Sie Ihr Array mit NaNs auf eine durch R teilbare Größe auffüllen und den Mittelwert mit scipy.nanmean verwenden.

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.])
27
shx2

Hier einige Ansätze, die entweder die lineare Interpolation oder die Fourier-Methode verwenden. Diese Methoden unterstützen sowohl Upsampling als auch Downsampling.

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

Wenn die Array-Größe nicht durch den Downsampling-Faktor (R) teilbar ist, können Sie das Array umformen (aufteilen), indem Sie np.linspace verwenden, gefolgt vom Mittelwert jedes Subarrays. 

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