Откуда возникает самое распространенное предупреждение Pandas, и как его обойти
Имя этому предупреждению - SettingWithCopyWarning. Оно вызывается из-за возможной проблемы при модификации данных, когда либо изменения вообще не произойдут, либо появятся там, где вы можете их не ожидать. Рассмотрим простой датафрейм:
import pandas as pd df1 = pd.DataFrame([[1,2,3], [4,5,6], [7,8,9], [10,11,12]], columns=['first', 'second', 'third']) df1
При различных способах обращения к датафрейму или его части может возвращаться либо представление (при модифицикации будет затронут датафрейм), либо копия данных (тогда изменения затронут только ее). Например, при таком обращении будет возвращена копия, и датафрейм модифицирован не будет
df1[df1['first'] > 3]['first'] = 1 df1
в то же время, если обратиться так, то изменения в первоисточнике появятся:
df1['first'][df1['first'] > 3] = 3 df1
Однако рекомендованным способом внесения изменений в срез датафрейма является с использованием оператора loc. Пересоздадим таблицу и применим данный способ:
df1 = pd.DataFrame([[1,2,3], [4,5,6], [7,8,9], [10,11,12]], columns=['first', 'second', 'third']) df1.loc[df1['first']>3, 'first'] = 3 df1
Вместе с тем большая доля предупреждений приходится при модификации ранее созданной ссылки или копии на датафрейм. Например, при указанном ниже способе возвращается копия и изменения не затронут первоисточник:
df2 = df1[['first']] df2['first'] /= 2 display(df2) display(df1)
С использованием же оператора loc вы гарантируете, что работаете со срезом первоисточника:
df2 = df1.loc[:,['first']] df2['first'] /= 2 display(df2) display(df1)
Если же вы хотите работать с копией и обезопасить себя от изменения первоисточника явно добавляйте метод copy при создании новой переменной, даже когда это происходит внутри функции. Например, часто предупреждение возникает при создании выборок из данных посредством train_test_split:
from sklearn.model_selection import train_test_split feat_tr, feat_ts = train_test_split(df1, test_size=0.5) feat_tr['first'] = feat_tr['first']**2 display(feat_tr) display(df1)
Несмотря на то, что функцией возвращается копия, вылетает предупреждение. Если же вы явно передадите в train_test_split параметр df1.copy(), оно не возникнет:
from sklearn.model_selection import train_test_split feat_tr, feat_ts = train_test_split(df1.copy(), test_size=0.5) feat_tr['first'] = feat_tr['first']**2 display(feat_tr) display(df1)
Более грубым способом обхода предупреждения является его запрет:
pd.options.mode.chained_assignment = None from sklearn.model_selection import train_test_split feat_tr, feat_ts = train_test_split(df1, test_size=0.5) feat_tr['first'] = feat_tr['first']**2 display(feat_tr) display(df1)
или вообще запрет всех предупреждений:
import warnings warnings.filterwarnings('ignore')
Последние два способа не рекомендую: лучше бороться с причиной, нежели закрывать на нее глаза.
Не пропустите ничего интересного и подписывайтесь на страницы канала в других социальных сетях: