Fillna dans plusieurs colonnes en place dans les Pandas de Python

j'ai une base de données pandas de types mixtes, certains sont des chaînes et certains sont des nombres. Je voudrais remplacer les valeurs NAN dans les colonnes string par '.', et les valeurs de NAN dans les colonnes flottantes par 0.

considérez ce petit exemple fictif:

df = pd.DataFrame({'Name':['Jack','Sue',pd.np.nan,'Bob','Alice','John'],
    'A': [1, 2.1, pd.np.nan, 4.7, 5.6, 6.8],
    'B': [.25, pd.np.nan, pd.np.nan, 4, 12.2, 14.4],
    'City':['Seattle','SF','LA','OC',pd.np.nan,pd.np.nan]})

Maintenant, je peux le faire en 3 lignes:

df['Name'].fillna('.',inplace=True)
df['City'].fillna('.',inplace=True)
df.fillna(0,inplace=True)

Puisqu'il s'agit d'une petite base de données, 3 lignes est probablement ok. Dans mon exemple réel (que je ne peux pas partager ici pour des raisons de confidentialité des données), j'ai beaucoup plus colonnes de chaîne et colonnes numériques. Alors j'ai fini par écrire beaucoup de lignes juste pour fillna. Y a-t-il une façon concise de le faire?

17
demandé sur Amir 2016-01-21 04:00:25

4 réponses

Vous pouvez utiliser apply pour vos colonnes avec la vérification dtype si numeric ou non en cochant dtype.kind:

res = df.apply(lambda x: x.fillna(0) if x.dtype.kind in 'biufc' else x.fillna('.'))

print(res)
     A      B     City   Name
0  1.0   0.25  Seattle   Jack
1  2.1   0.00       SF    Sue
2  0.0   0.00       LA      .
3  4.7   4.00       OC    Bob
4  5.6  12.20        .  Alice
5  6.8  14.40        .   John
14
répondu Anton Protopopov 2016-01-21 06:49:08

vous pouvez soit lister les colonnes string à la main ou les glaner à partir de df.dtypes. Une fois que vous avez la liste des colonnes string/object, vous pouvez appeler

# str_cols = ['Name','City']
str_cols = df.columns[df.dtypes==object]
df[str_cols] = df[str_cols].fillna('.')
df.fillna(0,inplace=True)
7
répondu Bob Baxley 2016-01-21 01:17:13

trouvé cette page en cherchant une réponse à ce problème, mais n'aimait pas les réponses existantes. J'ai fini par trouver quelque chose de mieux dans le DataFrame.documentation de fillna, et je me suis dit que je contribuerais pour n'importe qui d'autre qui se produirait sur ceci.

Si vous avez plusieurs colonnes, mais qui ne veulent remplacer le NaN dans un sous-ensemble d'entre eux, vous pouvez utiliser:

df.fillna({'Name':'.', 'City':'.'}, inplace=True)

cela vous permet également de spécifier des remplacements différents pour chaque colonne. Et si vous voulez aller de l'avant et de remplir toutes les autres NaN valeurs, vous pouvez simplement jeter un autre fillna sur la fin:

df.fillna({'Name':'.', 'City':'.'}, inplace=True).fillna(0, inplace=True)
4
répondu Rob Bulmahn 2018-08-02 13:27:28

définir une fonction:

def myfillna(series):
    if series.dtype is pd.np.dtype(float):
        return series.fillna(0)
    elif series.dtype is pd.np.dtype(object):
        return series.fillna('.')
    else:
        return series

vous pouvez ajouter d'autres elif déclarations, si vous voulez remplir une colonne d'une autre dtype d'une autre façon. Maintenant appliquez cette fonction sur toutes les colonnes du dataframe

df = df.apply(myfillna)

c'est la même chose que 'place'

1
répondu latorrefabian 2016-01-21 02:53:43