2017-08-02 1 views
2

J'ai un code qui crée une trame de données en utilisant pandas géantsRetirer les valeurs aberrantes de pandas géants dataframe python

import pandas as pd 
import numpy as np 

x = (g[0].time[:111673]) 
y = (g[0].data.f[:111673]) 
df = pd.DataFrame({'Time': x, 'Data': y}) 
#df 

Cette imprime:

  Data   Time 
0  -0.704239  7.304021 
1  -0.704239  7.352021 
2  -0.704239  7.400021 
3  -0.704239  7.448021 
4  -0.825279  7.496021 

Ce qui est génial, mais je sais qu'il ya des valeurs aberrantes dans ces données qui Je veux supprimé donc j'ai créé ce dataframe ci-dessous pour les signaler:

newdf = df.copy() 
Data = newdf.groupby('Data') 
newdf[np.abs(newdf.Data-newdf.Data.mean())<=(3*newdf.Data.std())] 
newdf['Outlier'] = Data.transform(lambda x: abs(x-x.mean()) > 1.96*x.std()) 
#newdf 

Ceci imprime t:

   Data   Time Outlier 
0  -0.704239  7.304021 False 
1  -0.704239  7.352021 False 
2  -0.704239  7.400021 False 
3  -0.704239  7.448021 False 
4  -0.825279  7.496021 False 

Dans l'exemple de mes données vous ne pouvez pas le voir, mais il y a peut-être 300 valeurs aberrantes et je veux les enlever sans déconner avec le dataframe d'origine, puis de les tracer ensemble comme une compression. Ma question est la suivante: Donc, au lieu d'imprimer faux/vrai, comment puis-je éliminer les valeurs aberrantes qui sont vraies? donc je peux éventuellement les tracer dans le même graphique pour une comparaison.

codes J'ai déjà essayé:

newdf[np.abs(newdf.Data-newdf.Data.mean())<=(1.96*newdf.Data.std())] 

newdf = df.copy() 
def replace_outliers_with_nan(df, stdvs): 
    newdf=pd.DataFrame() 
    for i, col in enumerate(df.sites.unique()): 
     df = pd.DataFrame(df[df.sites==col]) 
     idx = [np.abs(df-df.mean())<=(stdvs*df.std())] 
     df[idx==False]=np.nan 
     newdf[col] = df 
    return newdf 

Ces deux ne fonctionne pas, ils retourne la même quantité de points de données que mon dataframe d'origine mais je sais que si elle a enlevé les valeurs aberrantes la quantité de points serait inférieur à l'original.

Répondre

1

Il vous semble besoin boolean indexing avec ~ pour la condition inverse, car le filtre besoin de lignes seulement pas aberrantes (et baisse des valeurs aberrantes):

df1 = df[~df.groupby('Data').transform(lambda x: abs(x-x.mean()) > 1.96*x.std()).values] 
print (df1) 
     Data  Time 
0 -0.704239 7.304021 
1 -0.704239 7.352021 
2 -0.704239 7.400021 
3 -0.704239 7.448021 
4 -0.825279 7.496021 
+0

Quand j'ai essayé votre réponse que je reçois une erreur de valeur: 'augmenter ValueError (msg .format (dtype = dt)) ValueError: tableau booléen attendu pour la condition, pas float64' –

+0

Que retourne 'print (df.groupby ('Data'). transform (lambda x: abs (xx.mean())> 1,96 * x.std()))? pas la série «Vrai et faux»? – jezrael

+0

Je trouve un problème, vous avez besoin de '.values' pour convertir la série en tableau numpy. – jezrael