Was ist der schnellste / einfachste Weg, um nan- und inf / -inf-Werte aus einem Pandas-DataFrame zu löschen, ohne mode.use_inf_as_null zurückzusetzen? Ich möchte in der Lage sein, die Argumente subset und how von dropna zu verwenden, außer wenn inf Werte als fehlend angesehen werden, wie z.

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

Ist das möglich? Gibt es eine Möglichkeit, dropna anzuweisen, inf in die Definition fehlender Werte aufzunehmen?

255
user248237 5 Juli 2013 im 00:55

7 Antworten

Beste Antwort

Der einfachste Weg wäre, zuerst replace zu infizieren NaN:

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

Und verwenden Sie dann 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

Dieselbe Methode würde für eine Serie funktionieren.

372
Andy Hayden 4 Juli 2013 im 21:50

Eine weitere Lösung wäre die Verwendung der isin -Methode. Verwenden Sie diese Option, um festzustellen, ob jeder Wert unendlich ist oder fehlt, und verketten Sie dann die Methode all, 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]
6
Ted Petrou 3 Nov. 2017 im 18:34

Hier ist eine andere Methode, die .loc verwendet, um inf in einer Serie durch nan zu ersetzen:

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
15
Alexander 4 März 2016 im 00:20

Sie können pd.DataFrame.mask verwenden mit np.isinf. Sie sollten zunächst sicherstellen, dass Ihre Datenrahmenserien alle vom Typ float sind. Verwenden Sie dann dropna mit 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
4
jpp 28 Juni 2018 im 15:42

Die obige Lösung ändert die inf, 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)
7
has2k1 12 Feb. 2019 im 18:00

Verwendung (schnell und einfach):

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

Diese Antwort basiert auf DougRs Antwort 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
8
Markus Dutschke 18 März 2019 im 18:41

Im Optionskontext ist dies möglich, ohne use_inf_as_na dauerhaft festzulegen. Beispielsweise:

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

Natürlich kann es so eingestellt werden, dass inf dauerhaft mit NaN behandelt wird

pd.set_option('use_inf_as_na', True)

Ersetzen Sie bei älteren Versionen use_inf_as_na durch use_inf_as_null.

27
ayhan 2 Aug. 2019 im 20:47