Au début, j'ai essayé d'écrire du code qui ressemblait à ceci:

import numpy as np
import pandas as pd
np.random.seed(2016)
train = pd.DataFrame(np.random.choice([np.nan, 1, 2], size=(10, 3)), 
                     columns=['Age', 'SibSp', 'Parch'])

complete = train.dropna()    
complete['AgeGt15'] = complete['Age'] > 15

Après avoir obtenu SettingWithCopyWarning, j'ai essayé d'utiliser.loc:

complete.loc[:, 'AgeGt15'] = complete['Age'] > 15
complete.loc[:, 'WithFamily'] = complete['SibSp'] + complete['Parch'] > 0

Cependant, je reçois toujours le même avertissement. Ce qui donne?

20
Huey 7 août 2016 à 03:18

3 réponses

Meilleure réponse

Remarque: à partir de la version 0.24 de pandas, is_copy est obsolète et sera supprimé dans une future version. Bien que l'attribut privé _is_copy existe, le trait de soulignement indique que cet attribut ne fait pas partie de l'API publique et qu'il ne faut donc pas en dépendre. Par conséquent, à l'avenir, il semble que le seul moyen approprié de faire taire SettingWithCopyWarning sera de le faire à l'échelle mondiale:

pd.options.mode.chained_assignment = None

Lorsque complete = train.dropna() est exécuté, dropna peut renvoyer une copie, donc par prudence, Pandas place complete.is_copy sur un Vrai valeur:

In [220]: complete.is_copy
Out[220]: <weakref at 0x7f7f0b295b38; to 'DataFrame' at 0x7f7eee6fe668>

Cela permet aux Pandas de vous avertir plus tard, lorsque complete['AgeGt15'] = complete['Age'] > 15 sera exécuté que vous pouvez modifier une copie qui n'aura aucun effet sur train. Pour les débutants, cela peut être un avertissement utile. Dans votre cas, il semble que vous n'ayez pas l'intention de modifier train indirectement en modifiant complete. Par conséquent, l'avertissement n'est qu'un ennui insignifiant dans votre cas.

Vous pouvez désactiver l'avertissement en définissant,

complete.is_copy = False       # deprecated as of version 0.24

C'est plus rapide que de faire une copie réelle, et étouffe le SettingWithCopyWarning dans l'œuf (au point _check_setitem_copy est appelé):

def _check_setitem_copy(self, stacklevel=4, t='setting', force=False):
    if force or self.is_copy:
        ...

Si vous êtes vraiment certain de savoir ce que vous faites, vous pouvez désactiver le SettingWithCopyWarning globalement avec

pd.options.mode.chained_assignment = None # None|'warn'|'raise'

Une autre façon de faire taire l'avertissement est de faire une nouvelle copie:

complete = complete.copy()

Cependant, vous ne souhaiterez peut-être pas le faire si le DataFrame est volumineux, car la copie peut prendre beaucoup de temps et de mémoire, et il est complètement inutile (sauf pour faire taire un avertissement ) si vous savez que complete est déjà une copie.

21
unutbu 7 juil. 2019 à 12:07

Je le résous en créant une copie du dataframe:

complete = train.copy()
3
nnaqa 2 oct. 2018 à 05:35

Je pense que votre solution .loc fonctionnerait, si ce n'était pour les np.nan dans le bloc de données d'origine. Vous pouvez soit complete = train.dropna().reset_index() soit Pandas .assign () évitera SettingWithCopyWarning et est la méthode recommandée pour créer de nouvelles colonnes et renvoyer un nouvel objet de bloc de données. Votre exemple:

complete = complete.assign(**{'AgeGt15': np.where(complete['Age'] > 15, True, False)})
0
Jamie Edgecombe 8 nov. 2019 à 12:29