Короткий ответ
df[df['status'] == 'active'] может вернуть не независимую копию, а представление (view) исходного DataFrame, поэтому присвоение нового столбца через df_filtered['flag'] = 1 неоднозначно для pandas и порождает предупреждение; правильное решение — явно создать копию через .copy() или использовать .loc для присвоения.
Как это работает подробнее
- Как это работает: булева индексация в pandas иногда возвращает копию, а иногда представление в зависимости от внутренней структуры данных, и pandas не может гарантировать, что изменение
df_filteredне должно было повлиять наdf; отсюдаSettingWithCopyWarning— предупреждение о потенциально непредсказуемом поведении, а не гарантированная ошибка.
Пример кода
setting_with_copy.py
df_filtered = df[df['status'] == 'active']
df_filtered['flag'] = 1 # SettingWithCopyWarning
df_filtered = df[df['status'] == 'active'].copy()
df_filtered['flag'] = 1Что использовать на практике
- На практике: если предполагается, что
df_filtered— независимый объект, его нужно явно создать черезdf_filtered = df[df['status'] == 'active'].copy(); если же цель — изменить исходныйdf, то нужно использоватьdf.loc[df['status'] == 'active', 'flag'] = 1напрямую, без промежуточной переменной. В pandas 2.x с режимом Copy-on-Write (pd.options.mode.copy_on_write = True) эта проблема частично снимается на уровне поведения, но писать код без неявных предположений по-прежнему считается хорошей практикой код-ревью. - Пример и проверка. Проблемный код: Исправление: Проверка на ревью: после исправления код выполняется без предупреждений, а id(df_filtered) != id(df) подтверждает, что это независимый объект, изменения в котором не затрагивают исходный df.
Подводные камни
- Частые ошибки: игнорировать
SettingWithCopyWarningкак «просто предупреждение», хотя иногда это сигнал, что изменения вообще не применились к данным, которые дальше используются в расчётах; делать длинные цепочкиdf[cond1][cond2]['col'] = value(chained assignment), где непонятно, к какому объекту относится присваивание.