SettingWithCopyWarning veut dire : Pandas n’est pas sûr que votre affectation touche le DataFrame que vous croyez. Vous avez peut-être écrit dans une copie temporaire. La modification peut être visible, ou disparaître à la ligne suivante, selon la version, la disposition mémoire et le copy-on-write.
Ce n’est pas une erreur de syntaxe. C’est un aveu d’ambiguïté. L’ignorer, c’est accepter un résultat non déterministe.
Presque toujours d’une indexation chaînée : deux crochets, deux opérations.
df[df["statut"] == "actif"]["remise"] = 0.1La première indexation fabrique un objet dont Pandas ne garantit pas qu’il soit une vue. La seconde écrit dedans. Si c’était une copie, df n’a pas bougé — et vous ne le voyez pas, parce que l’affectation « a marché » sur un objet jeté.
La même intention, en une opération :
df.loc[df["statut"] == "actif", "remise"] = 0.1Un seul __setitem__, étiquettes explicites. L’avertissement disparaît, et le contrat est clair.
Depuis Pandas 2, le copy-on-write rend cette ambiguïté plus honnête : l’écriture chaînée ne propage plus vers l’original, et les versions récentes peuvent lever une erreur plutôt qu’un warning. En entretien, mentionner CoW montre que vous suivez l’outil, pas un blog de 2018. Ça ne change pas la règle de style : pas d’indexation chaînée à l’écriture.
L’autre source fréquente : un filtre stocké dans une variable, puis muté.
actifs = df[df["statut"] == "actif"]
actifs["remise"] = 0.1 # warning ou no-op selon le mode
df.loc[actifs.index, "remise"] = 0.1Si actifs doit vivre sa vie, actifs = df.loc[...].copy() puis vous mutuez la copie en connaissance de cause.
« Le warning n’est pas apparu, donc c’est bon ? »
Non. L’absence d’avertissement ne prouve pas que vous teniez une vue. Certaines chaînes passent silencieuse. La preuve, c’est une affectation par loc sur l’objet racine, ou une copie assumée.
« Et pour créer une colonne sur un sous-ensemble ? »
Même règle. df.loc[masque, "nouvelle"] = valeur crée ou écrase la colonne aux lignes concernées, NaN ailleurs. Vous ne partez pas d’une slice pour ajouter une colonne à df.