Панды все еще получают SettingWithCopyWarning даже после использования.loc
Сначала я попытался написать код, который выглядел так:
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
После получения SettingWithCopyWarning я попытался использовать.loc:
complete.loc[:, 'AgeGt15'] = complete['Age'] > 15
complete.loc[:, 'WithFamily'] = complete['SibSp'] + complete['Parch'] > 0
Тем не менее, я все еще получаю то же предупреждение. Что дает?
2 ответа
Примечание. Начиная с версии 0.24 для панд, is_copy
устарела и будет удалена в следующей версии. Пока приватный атрибут _is_copy
существует, подчеркивание указывает, что этот атрибут не является частью общедоступного API и поэтому не должен зависеть от него. Поэтому, идя вперед, кажется, что единственный правильный способ заставить замолчать SettingWithCopyWarning
будет делать это глобально
pd.options.mode.chained_assignment = None
когда complete = train.dropna()
выполняется, dropna
может вернуть копию, так что из-за предосторожности, Pandas устанавливает complete.is_copy
к истинному значению:
In [220]: complete.is_copy
Out[220]: <weakref at 0x7f7f0b295b38; to 'DataFrame' at 0x7f7eee6fe668>
Это позволяет Пандам предупредить вас позже, когда complete['AgeGt15'] = complete['Age'] > 15
выполняется, что вы можете изменять копию, которая не будет влиять на train
, Для начинающих это может быть полезным предупреждением. В вашем случае, похоже, вы не собираетесь изменять train
косвенно путем изменения complete
, Поэтому предупреждение - это просто бессмысленное раздражение в вашем случае.
Вы можете отключить предупреждение, установив
complete.is_copy = False
Это быстрее, чем сделать реальную копию, и SettingWithCopyWarning
в зародыше (в точке, где _check_setitem_copy
называется):
def _check_setitem_copy(self, stacklevel=4, t='setting', force=False):
if force or self.is_copy:
...
Если вы действительно уверены, что знаете, что делаете, вы можете отключить SettingWithCopyWarning
глобально с
pd.options.mode.chained_assignment = None # None|'warn'|'raise'
Я разрешаю это, создавая копию dataframe:
complete = train.copy()
Я думаю твой .loc
решение сработало бы, если бы не np.nan
s в исходном фрейме данных. Вы могли либоcomplete = train.dropna().reset_index()
или Pandas .assign() избегаетSettingWithCopyWarning
и это рекомендуемый способ создания новых столбцов с возвратом нового объекта фрейма данных. Ваш пример:
complete = complete.assign(**{'AgeGt15': np.where(complete['Age'] > 15, True, False)})