unendliche Werte aus Datenrahmen in Pandas löschen?


219

Was ist der schnellste / einfachste Weg, um Nano- und Inf / Inf-Werte aus einem Pandas-DataFrame zu löschen, ohne sie zurückzusetzen mode.use_inf_as_null? Ich möchte in der Lage sein, die Argumente subsetund howvon zu verwenden dropna, außer bei infWerten, die als fehlend gelten, wie:

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

Ist das möglich? Gibt es eine Möglichkeit zu sagen , dropnaenthalten infin ihrer Definition Werte fehlt?

Antworten:


416

Der einfachste Weg wäre, zuerst replaceNaN zu infizieren:

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

und dann verwenden Sie die dropna:

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

Beispielsweise:

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

Die gleiche Methode würde für eine Serie funktionieren.


2
Wie kann man die infWerte gegen eine vordefinierte intwie 0in einer bestimmten Spalte "austauschen" ?
3kstc

4
@ 3kstc verwenden .replace(..., 0). Um nur auf Spalten zu tun, aktualisieren Sie diese Spalten, dhdf[cols] = df[cols].replace(..., 0)
Andy Hayden

3
Vielleicht lohnt es sich anzugeben, dass replacedies nicht an Ort und Stelle funktioniert, sodass eine neue DataFramezurückgegeben wird
Marco

36

Mit Optionskontext ist dies ohne permanente Einstellung möglich use_inf_as_na. Beispielsweise:

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

Natürlich kann es zu behandeln eingestellt wird infals NaNdauerhaft mit

pd.set_option('use_inf_as_na', True)

Für ältere Versionen ersetzen use_inf_as_namit use_inf_as_null.


6
Dies ist die am besten lesbare Antwort und folglich die beste, obwohl sie in Buchstaben (aber nicht im Geiste) gegen die ursprüngliche Frage verstößt.
Ijoseph

2
Pandas ab (mindestens) 0.24: use_inf_as_nullwaren veraltet und werden in einer zukünftigen Version entfernt. Verwenden Sie use_inf_as_nastattdessen. Antwort hinzufügen / aktualisieren?
Håkon T.

1
Dies ist eine bessere Wahl, um infauf globaler Einstellungsebene als auf operativer Ebene als Nullen zu behandeln . Dies könnte möglicherweise Zeit sparen, wenn die Werte zuerst eingegeben werden.
TaoPR

15

Hier ist eine andere Methode, mit .locder inf in einer Serie durch nan ersetzt wird:

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

Als Antwort auf die ursprüngliche Frage:

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

11

Verwendung (schnell und einfach):

df = df[np.isfinite(df).all(1)]

Diese Antwort basiert auf der Antwort von DougR in einer anderen Frage. Hier ein Beispielcode:

import pandas as pd
import numpy as np
df=pd.DataFrame([1,2,3,np.nan,4,np.inf,5,-np.inf,6])
print('Input:\n',df,sep='')
df = df[np.isfinite(df).all(1)]
print('\nDropped:\n',df,sep='')

Ergebnis:

Input:
    0
0  1.0000
1  2.0000
2  3.0000
3     NaN
4  4.0000
5     inf
6  5.0000
7    -inf
8  6.0000

Dropped:
     0
0  1.0
1  2.0
2  3.0
4  4.0
6  5.0
8  6.0

7

Eine weitere Lösung wäre die Verwendung der isinMethode. Verwenden Sie diese Option, um festzustellen, ob jeder Wert unendlich ist oder fehlt, und verketten Sie dann die allMethode, um festzustellen, ob alle Werte in den Zeilen unendlich sind oder fehlen.

Verwenden Sie schließlich die Negation dieses Ergebnisses, um die Zeilen auszuwählen, die nicht alle unendlichen oder fehlenden Werte über die boolesche Indizierung haben.

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

7

Die obige Lösung ändert die infs, die sich nicht in den Zielspalten befinden. Um dem abzuhelfen,

lst = [np.inf, -np.inf]
to_replace = {v: lst for v in ['col1', 'col2']}
df.replace(to_replace, np.nan)

3
Python 2.7 und höher Unterstützung diktieren Verständnis:{v: lst for v in cols}
Aryeh Leib Taurog

4

Sie können pd.DataFrame.maskmit verwenden np.isinf. Sie sollten zuerst sicherstellen, dass Ihre Datenrahmenserien alle vom Typ sind float. Verwenden Sie dann dropnamit Ihrer vorhandenen Logik.

print(df)

       col1      col2
0 -0.441406       inf
1 -0.321105      -inf
2 -0.412857  2.223047
3 -0.356610  2.513048

df = df.mask(np.isinf(df))

print(df)

       col1      col2
0 -0.441406       NaN
1 -0.321105       NaN
2 -0.412857  2.223047
3 -0.356610  2.513048
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.