2013-07-04 32 views
84

qual è il modo più veloce/semplice per rilasciare i valori nan e inf/-inf da un DataFrame panda senza reimpostare mode.use_inf_as_null? Mi piacerebbe essere in grado di utilizzare i subset e how argomenti di dropna, se non con inf valori considerati mancanti, come:lasciando cadere valori infiniti dai dataframes nei panda?

df.dropna(subset=["col1", "col2"], how="all", with_inf=True) 

è possibile? C'è un modo per dire a dropna di includere inf nella sua definizione di valori mancanti?

risposta

162

Il modo più semplice sarebbe quella di primi replace INFS NaN:

df.replace([np.inf, -np.inf], np.nan) 

e quindi utilizzare il dropna:

df.replace([np.inf, -np.inf], np.nan).dropna(subset=["col1", "col2"], how="all") 

Ad esempio:

In [11]: df = pd.DataFrame([1, 2, np.inf, -np.inf]) 

In [12]: df.replace([np.inf, -np.inf], np.nan) 
Out[12]: 
    0 
0 1 
1 2 
2 NaN 
3 NaN 

Lo stesso metodo funzionerebbe per una serie.

5

La soluzione sopra riportata modificherà i valori inf che non si trovano nelle colonne di destinazione. Per ovviare a questo,

lst = [np.inf, -np.inf] 
to_replace = dict((v, lst) for v in ['col1', 'col2']) 
df.replace(to_replace, np.nan) 
+2

pitone 2.7 e superiori comprensioni supporto dict: '{v: LST per v in colli}' –

10

Ecco un altro metodo che utilizza .loc per sostituire inf con nan su una Serie:

s.loc[(~np.isfinite(s)) & s.notnull()] = np.nan 

Così, in risposta alla domanda iniziale:

df = pd.DataFrame(np.ones((3, 3)), columns=list('ABC')) 

for i in range(3): 
    df.iat[i, i] = np.inf 

df 
      A   B   C 
0  inf 1.000000 1.000000 
1 1.000000  inf 1.000000 
2 1.000000 1.000000  inf 

df.sum() 
A inf 
B inf 
C inf 
dtype: float64 

df.apply(lambda s: s[np.isfinite(s)].dropna()).sum() 
A 2 
B 2 
C 2 
dtype: float64 
7

Con contesto delle opzioni, questo è possibile senza impostare permanentemente use_inf_as_null. Per esempio:

with pd.option_context('mode.use_inf_as_null', True): 
    df = df.dropna(subset=['col1', 'col2'], how='all') 

Naturalmente può essere impostato per il trattamento di inf come NaN permanente con pd.set_option('use_inf_as_null', True) troppo.

+1

Questa è la risposta più leggibile ed è quindi il migliore, anche se esso viola nella lettera (ma non nello spirito) la domanda originale – ijoseph

1

Un'altra soluzione potrebbe essere l'utilizzo del metodo isin. Usalo per determinare se ogni valore è infinito o mancante e quindi concatenare il metodo all per determinare se tutti i valori nelle righe sono infiniti o mancanti.

Infine, utilizzare la negazione di tale risultato per selezionare le righe che non hanno tutti i valori infiniti o mancanti tramite l'indicizzazione booleana.

all_inf_or_nan = df.isin([np.inf, -np.inf, np.nan]).all(axis='columns') 
df[~all_inf_or_nan] 
Problemi correlati