Опция mode.chained_assignment
Опция mode.chained_assignment управляет реакцией Pandas
на цепочные присваивания (chained assignments) - ситуации,
когда операции присваивания выполняются в цепочке обращений
к DataFrame, например, df['a'][df['a'] > 3] = 5.
Такие конструкции могут работать непредсказуемо, так как
не всегда понятно, создаётся копия данных или представление.
Данная опция может принимать три значения: 'warn'
(выводить предупреждение при обнаружении цепочных присваиваний,
установлено по умолчанию), 'raise' (генерировать
исключение) и None (полностью отключить проверку).
Синтаксис
pd.set_option('mode.chained_assignment', value)
current_value = pd.get_option('mode.chained_assignment')
где ⁅i⁆value⁅/i⁆ может быть 'warn', 'raise' или None.
Пример
Рассмотрим поведение по умолчанию с предупреждениями:
import pandas as pd
df = pd.DataFrame({
'a': [1, 2, 3, 4, 5],
'b': [10, 20, 30, 40, 50]
})
# Цепочное присваивание вызовет предупреждение
df['a'][df['a'] > 3] = 0
print(df)
Результат выполнения кода:
SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame
a b
0 1 10
1 2 20
2 3 30
3 0 40
4 0 50
Как видно, код отработал, но появилось предупреждение.
Пример
Отключим предупреждения установкой значения None:
import pandas as pd
pd.set_option('mode.chained_assignment', None)
df = pd.DataFrame({
'a': [1, 2, 3, 4, 5],
'b': [10, 20, 30, 40, 50]
})
# Предупреждение не будет выведено
df['a'][df['a'] > 3] = 0
print(df)
Результат выполнения кода:
a b
0 1 10
1 2 20
2 3 30
3 0 40
4 0 50
Теперь код выполняется без предупреждений, что может быть удобно в продакшене, но скрывает потенциальные проблемы.
Пример
Установим режим возбуждения исключения:
import pandas as pd
pd.set_option('mode.chained_assignment', 'raise')
df = pd.DataFrame({
'a': [1, 2, 3, 4, 5],
'b': [10, 20, 30, 40, 50]
})
try:
# Будет возбуждено исключение
df['a'][df['a'] > 3] = 0
except Exception as e:
print(type(e).__name__ + ":", str(e))
Результат выполнения кода:
"ChainedAssignmentError: A value is trying to be set on a copy of a slice from a DataFrame"
В режиме 'raise' вместо предупреждения возбуждается
исключение ChainedAssignmentError, что помогает
обнаруживать проблемные места на этапе разработки.
Пример
Правильный способ избежать цепочных присваиваний:
import pandas as pd
pd.set_option('mode.chained_assignment', 'warn')
df = pd.DataFrame({
'a': [1, 2, 3, 4, 5],
'b': [10, 20, 30, 40, 50]
})
# Используем loc для явного присваивания
df.loc[df['a'] > 3, 'a'] = 0
print(df)
Результат выполнения кода:
a b
0 1 10
1 2 20
2 3 30
3 0 40
4 0 50
Использование loc - это корректный способ выполнить
условное присваивание без создания цепочных обращений.
Смотрите также
-
опция
set_option,
которая устанавливает значения глобальных опций Pandas -
опция
get_option,
которая возвращает текущие значения глобальных опций -
опция
mode.copy_on_write,
которая меняет модель копирования данных при присваиваниях -
метод
copy,
который создает явную копию DataFrame для безопасной работы