2017-10-07 8 views
1

J'ai une trame de données avec des colonnes numériques et de chaînes.Pandas: remplacer les valeurs aberrantes (3 sigma) dans toutes les colonnes numériques d'une trame de données avec NaN

import numpy as np 
import pandas as pd 
from scipy.stats import zscore 

data = {'c1' : [1., 2., 3., 4.], 'c2' : [4., 3., 2., 1.], 'c3' : [5., 6., 7000., 8.], 
     'c4' : [8., 7., 6., 10000.], 'c5' : ['a', 'b', 'c', 'd']} 

Je souhaite remplacer les valeurs aberrantes dans les colonnes numériques par NaN.

c1 c2 c3 c4 c5 
0 1.0 4.0 5.0 8.0 a 
1 2.0 3.0 6.0 7.0 b 
2 3.0 2.0 NaN 6.0 c 
3 4.0 1.0 8.0 NaN d 

Ce code fait ce que je veux faire.

df = pd.DataFrame(data) 
allcol = list(df) 
numcol = [x for x in allcol if x not in ('c5')] 
df[numcol] = df[numcol].mask(~df[numcol].apply(lambda x: zscore(x) < 1.5, axis=1)) 

Vous vous demandez si vous savez mieux et plus simple solution ...

Répondre

1

Vous pouvez définir 'c5' dans l'index, puis utilisez:

df1 = df.set_index('c5') 
df1.where(df1.apply(zscore).lt(1.5)).reset_index().reindex_axis(df.columns,1) 

Sortie:

c1 c2 c3 c4 c5 
0 1.0 4.0 5.0 8.0 a 
1 2.0 3.0 6.0 7.0 b 
2 3.0 2.0 NaN 6.0 c 
3 4.0 1.0 8.0 NaN d 
+1

Ou peut-on utiliser 'df.select_dtypes (exclude = ['object'])' obtenir la colonne numérique :) – Wen

+0

@Wen une bonne idée aussi! –