2015-04-20 1 views
2

j'ai vu plusieurs solutions qui se rapprochent de résoudre mon problèmeRetirer les valeurs aberrantes (+/- 3 std) et le remplacer par np.nan en Python/pandas géants

link1 link2

mais ils ont pas aidé moi réussir jusqu'à présent.

Je crois que la solution suivante est ce que je dois, mais continuer à obtenir une erreur (et je n'ai pas les points de réputation pour commenter/question là-dessus): link

(je reçois l'erreur suivante , mais je ne comprends pas où .copy() ou ajouter un « inplace=True » lors de l'administration de la commande suivante df2=df.groupby('install_site').transform(replace):

SettingWithCopyWarning. une valeur tente de régler sur une copie d'une tranche d'un dataframe Essayez d'utiliser .loc[row_indexer,col_indexer] = value au lieu de

Voir les mises en garde dans la documentation: link

, j'ai essayé de trouver ma propre version, mais je continue à me coincer. Voici.

J'ai une trame de données indexée par le temps avec des colonnes pour les valeurs de site (valeurs de chaîne pour de nombreux sites différents) et flottantes.

time_index   site  val 

Je voudrais passer par la colonne « val », regroupés par site, et remplacer les valeurs aberrantes (les +/- 3 écarts-types de la moyenne) avec un NaN (pour chaque groupe).

Lorsque j'utilise la fonction suivante, je ne peux pas indexer la trame de données avec mon vecteur Vrai/faux:

def replace_outliers_with_nan(df, stdvs): 
    dfnew=pd.DataFrame() 
    for i, col in enumerate(df.sites.unique()): 
     dftmp = pd.DataFrame(df[df.sites==col]) 
     idx = [np.abs(dftmp-dftmp.mean())<=(stdvs*dftmp.std())] #boolean vector of T/F's 
     dftmp[idx==False]=np.nan #this is where the problem lies, I believe 
     dfnew[col] = dftmp 
    return dfnew 

De plus, je crains la fonction ci-dessus prendra un temps très long sur 7 millions + lignes , c'est pourquoi j'espérais utiliser l'option groupby function.

+0

Cette erreur que vous obtenez est juste un avertissement. Il semble parfois arriver même lorsque l'opération réussit. Avez-vous vérifié si l'utilisation de cette méthode fonctionne malgré le message? – BrenBarn

Répondre

5

Si je vous ai bien compris, il n'est pas nécessaire de parcourir les colonnes. Cette solution remplace toutes les valeurs qui s'écartent de plus de trois écarts-types de groupe avec NaN.

def replace(group, stds): 
    group[np.abs(group - group.mean()) > stds * group.std()] = np.nan 
    return group 

# df is your DataFrame 
df.loc[:, df.columns != group_column] = df.groupby(group_column).transform(lambda g: replace(g, 3)) 
+0

Merci beaucoup @RickardSjogren. Cela fonctionne très bien! J'obtiens l'erreur d'indexation-contre-copie, mais cela fonctionne à la fin. Très appréciée!! –

+0

pourriez-vous suggérer un moyen de l'appliquer indépendamment à chaque colonne d'une trame de données (c'est-à-dire, remplacer les valeurs qui sont> 3std de la moyenne pour chaque colonne)? J'ai du mal à le faire fonctionner et je continue à me retrouver avec un dataframe vide. –

+0

J'espérais que vous pourriez m'aider avec ce qui précède, @RickardSjogren –