Invece di indicizzare, è possibile avvicinarsi a questa con una prospettiva di elaborazione del segnale. In pratica stai eseguendo un discrete convolution del tuo segnale di input con un kernel a 7 tasti in cui i tre coefficienti centrali sono 0 mentre gli estremi sono 1, e dal momento che vuoi calcolare la media, devi moltiplicare tutti i valori per (1/4)
. Tuttavia, non stai calcolando la convoluzione di tutti gli elementi, ma ne parleremo più tardi. Un modo è quello di utilizzare scipy.ndimage.filters.convolve1d
per questo:
import numpy as np
from scipy.ndimage import filters
d = np.arange(1, 21, dtype=np.float)
ker = (1.0/4.0)*np.array([1,1,0,0,0,1,1], dtype=np.float)
out = filters.convolve1d(d, ker)[3:-3:2]
Perché stai usando un kernel 7 rubinetto, convoluzione si estenderà l'uscita per 3 a sinistra e 3 a destra, quindi è necessario fare in modo di ritaglia il primo e l'ultimo tre elementi. Si vuole anche saltare l'elemento ogni altro elemento perché la convoluzione implica una finestra scorrevole, ma si desidera scartare ogni altro elemento in modo da ottenere il risultato desiderato.
Otteniamo questo per out
:
In [47]: out
Out[47]: array([ 4., 6., 8., 10., 12., 14., 16.])
di controllare due volte per vedere se abbiamo il giusto risultato, provare alcuni esempi di calcolo per ogni elemento. Il primo elemento è uguale a (1+2+6+7)/4 = 4
. Il secondo elemento è uguale a (3+4+8+9)/4 = 6
e così via.
Per una soluzione con meno mal di testa, prova a numpy.convolve
con la bandiera mode=valid
. Ciò evita il taglio fuori dalla imbottitura extra a sinistra ea destra, ma sarà ancora bisogno di saltare ogni altro elemento però:
import numpy as np
d = np.arange(1, 21, dtype=np.float)
ker = (1.0/4.0)*np.array([1,1,0,0,0,1,1], dtype=np.float)
out = np.convolve(d, ker, mode='valid')[::2]
Inoltre otteniamo:
In [59]: out
Out[59]: array([ 4., 6., 8., 10., 12., 14., 16.])
Infine, se si vuole indicizzazione, qualcosa di simile può essere sufficiente:
length = len(d[6::2])
out = np.array([(a+b+c+e)/4.0 for (a,b,c,e) in zip(d[::2][:length], d[1::2][:length], d[5::2][:length], d[6::2])])
otteniamo:
In [69]: out
Out[69]: array([ 4., 6., 8., 10., 12., 14., 16.])
Questo è davvero brutto, ma funziona. La lunghezza totale del segnale è regolata dal fatto che la fine di ogni finestra è al settimo indice. La lunghezza di questo array che contiene questi indici determina la lunghezza finale del segnale. Inoltre, si noti che per un elemento in una finestra, il suo elemento successivo può essere trovato saltando ogni altro elemento fino alla fine dell'array. Ci sono 4 di queste sequenze in totale e noi semplicemente zip
su queste 4 sequenze in cui ogni sequenza salta ogni altro elemento, ma c'è un offset a cui iniziamo.La prima sequenza inizia con l'offset 0, il successivo a 1, il successivo a 5 e il successivo a 6. Raccogliamo questi quattro elementi e li valutiamo mediamente, quindi saltiamo su tutti gli array fino alla fine.
BTW, mi piace ancora la convoluzione.
come hai scelto quei numeri 1,2,6,7? quali sono le regole? –
@omri_saadon due elementi consecutivi e dopo 5 elementi altri due elementi consequenziali. – Borys
Posso vedere che qui ci sono dati interpolati, possibilmente dati di immagine. Perché non riformulare la domanda in modo che sia chiara la sequenza necessaria per ciascuno dei 2 set? – gburton