web-dev-qa-db-fra.com

abandonner des valeurs infinies des images dans les pandas?

quel est le moyen le plus rapide/le plus simple de supprimer les valeurs nan et inf/-inf d'un pandas DataFrame sans réinitialiser mode.use_inf_as_null? J'aimerais pouvoir utiliser les arguments subset et how de dropna, sauf avec les valeurs inf considérées manquantes, comme:

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

est-ce possible? Existe-t-il un moyen de dire à dropna d'inclure inf dans sa définition des valeurs manquantes?

170
user248237

Le moyen le plus simple serait de commencer par replace infs to NaN:

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

puis utilisez le dropna :

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

Par exemple:

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

La même méthode fonctionnerait pour une série.

315
Andy Hayden

Avec l'option context, cela est possible sans régler en permanence use_inf_as_na. Par exemple:

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

Bien sûr, il peut être configuré pour traiter inf comme NaN de manière permanente avec

pd.set_option('use_inf_as_na', True)

Pour les versions plus anciennes, remplacez use_inf_as_na par use_inf_as_null.

19
ayhan

Voici une autre méthode utilisant .loc pour remplacer inf par nan sur une série:

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

Donc, en réponse à la question initiale:

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

La solution ci-dessus modifiera les infs qui ne figurent pas dans les colonnes cibles. Pour y remédier,

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

Une autre solution consisterait à utiliser la méthode isin. Utilisez-le pour déterminer si chaque valeur est infinie ou manquante, puis enchaînez la méthode all pour déterminer si toutes les valeurs des lignes sont infinies ou manquantes.

Enfin, utilisez la négation de ce résultat pour sélectionner les lignes qui n'ont pas toutes les valeurs infinies ou manquantes via l'indexation booléenne.

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

Utilisez (rapide et simple):

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

Cette réponse est basée sur réponse de DougR dans une autre question. Voici un exemple de code:

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='')

Résultat:

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
5
Markus Dutschke

Vous pouvez utiliser pd.DataFrame.mask avec np.isinf . Vous devez d'abord vous assurer que vos séries de données sont de type float. Puis utilisez dropna avec votre logique existante.

_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
_
2
jpp