web-dev-qa-db-fra.com

Sous-échantillonner un tableau 1D numpy

J'ai un tableau numpy 1-D que je voudrais sous-échantillonner. L'une des méthodes suivantes est acceptable si le raster de sous-échantillonnage ne correspond pas parfaitement aux données:

  • chevauchement des intervalles de sous-échantillon
  • convertir le nombre de valeurs restant à la fin en une valeur sous-échantillonnée séparée
  • interpoler pour s'adapter au raster

fondamentalement si j'ai 

1 2 6 2 1

et je sous-échantillonne d'un facteur 3, tout ce qui suit est ok:

3 3

3 1.5

ou quelle que soit une interpolation me donnerait ici.

Je cherche simplement le moyen le plus rapide et le plus simple de le faire.

J'ai trouvé scipy.signal.decimate , mais cela ressemble à cela décime les valeurs (les supprime au besoin et n'en laisse qu'une dans X). scipy.signal.resample semble avoir le bon nom, mais je ne comprends pas où ils vont avec la chose entière dans la description. Mon signal n'est pas particulièrement périodique.

Pourriez-vous me donner un coup de main ici? Cela semble être une tâche très simple à faire, mais toutes ces fonctions sont assez complexes ...

18
TheChymera

Dans le cas simple où la taille de votre tableau est divisible par le facteur de sous-échantillonnage (R), vous pouvez reshape votre tableau et prendre la moyenne le long du nouvel axe:

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

Dans le cas général, vous pouvez compléter votre tableau avec NaNs à une taille divisible par R et prendre la moyenne à l'aide de 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.])
27
shx2

Si la taille du tableau n'est pas divisible par le facteur de sous-échantillonnage (R), il est possible de remodeler (fractionner) le tableau en utilisant np.linspace suivi de la moyenne de chaque sous-tableau. 

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