2012-10-31 28 views
7

Ho un array 1 dimensionale A di float che è principalmente buono ma mancano alcuni valori. I dati mancanti sono sostituiti con nan (non un numero). Devo sostituire i valori mancanti nella matrice mediante interpolazione lineare dai buoni valori vicini. Così, per esempio:Interpolazione lineare con numpy.interp

F7(np.array([10.,20.,nan,40.,50.,nan,30.])) 

dovrebbe restituire

np.array([10.,20.,30.,40.,50.,40.,30.]). 

Qual è il miglior modo di fare di questo con Python?

Qualsiasi aiuto sarebbe molto apprezzato

Grazie

+3

Vuoi davvero dire interpolazione lineare? O vuoi dire in media? - Suppongo anche che il primo e l'ultimo valore siano garantiti per non essere NaN? – mgilson

+0

Era solo una media nell'esempio. L'interpolazione lineare dovrebbe davvero trovare i valori mancanti in un'equazione lineare. E sì, il primo e l'ultimo valore non sono NaN. –

risposta

11

Si potrebbe utilizzare scipy.interpolate.interp1d:

>>> from scipy.interpolate import interp1d 
>>> import numpy as np 
>>> x = np.array([10., 20., np.nan, 40., 50., np.nan, 30.]) 
>>> not_nan = np.logical_not(np.isnan(x)) 
>>> indices = np.arange(len(x)) 
>>> interp = interp1d(indices[not_nan], x[not_nan]) 
>>> interp(indices) 
array([ 10., 20., 30., 40., 50., 40., 30.]) 

EDIT: mi c'è voluto un po 'per capire come np.interp opere, ma che può fare anche il lavoro:

>>> np.interp(indices, indices[not_nan], x[not_nan]) 
array([ 10., 20., 30., 40., 50., 40., 30.]) 
+1

Penso che userò 'len (x)' piuttosto che '* x.shape'. Sembra un po 'più esplicito dato che stiamo facendo solo 1D (e questo non generalizza a più dimensioni) - ma +1 per una soluzione interpolata funzionante. – mgilson

+0

Invece di generare 'np.arange (len (x))' due volte, perché non farlo una sola volta e memorizzare il risultato? Inoltre, non penso che tu abbia bisogno di "scipy" per questo. 'np.interp' sembra che farebbe la stessa cosa in questo scenario – mgilson

+0

@mgilson: avevi ragione tre volte. Grazie, ha aggiornato la risposta. –

6

Vorrei andare con pandas. Un approccio minimalista con un oneliner:

from pandas import * 
a=np.array([10.,20.,nan,40.,50.,nan,30.]) 
Series(a).interpolate() 

Out[219]: 
0 10 
1 20 
2 30 
3 40 
4 50 
5 40 
6 30 

Oppure, se si vuole mantenere come un array:

Series(a).interpolate().values 

Out[221]: 
array([ 10., 20., 30., 40., 50., 40., 30.]) 
+0

@larsmans - stavo solo per suggerire .valori, che restituisce anche un array :) – root

+0

L'ho visto, cancellato il mio commento. Panda è ancora nell'elenco delle "librerie da imparare" :) –