SettingwithCopy при создании нового столбца и при удалении строк NaN
Я искал вокруг, читая документы панд здесь и пробуя разные строки кода из вопросов, опубликованных здесь и здесь, и я не могу отделаться от настройки предупреждением о копировании. Я бы предпочел научиться кодировать его "правильным" способом, а не просто игнорировать предупреждения.
Следующие строки кода находятся внутри цикла for, и я не хочу генерировать это предупреждение много раз, потому что это может замедлить процесс.
Я пытаюсь создать новый столбец с именем: 'E'+vs, где vs - строка в списке в цикле for
Но для каждого из них я получаю следующее предупреждение, даже с последними 3 строками:
SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead
Вот проблемные строки, которые я пробовал до сих пор:
#based on research, the first two seem to be the "wrong" way
df_out['E'+vs] = df_out[kvs].rolling(v).mean().copy()
df_out['E'+vs] = df_out[kvs].rolling(v).mean()
df_out.loc[:,'E'+vs] = df_out[kvs].rolling(v).mean().copy()
df_out.loc[:,'E'+vs] = df_out[kvs].rolling(v).mean()
df_out.loc[:,'E'+vs] = df_out.loc[:,kvs].rolling(v).mean()
Другой, который дает SettingWithCopyWarning это:
df_out.dropna(inplace=True,axis=0)
Этот также дал предупреждение (но я подумал, что это будет)
df_out = df_out.dropna(inplace=True,axis=0)
Как правильно выполнить обе эти операции?
РЕДАКТИРОВАТЬ: Вот код, который произвел оригинальный df_out
df_out= pd.concat([vol.Date[1:-1], ret.Return_Time[:-2], vol.Freq_Time[:-2],
vol.Freq_Time[:-1].shift(-1), vol.Freq_Time[:].shift(-2)],
axis=1).dropna().set_index('Date')
2 ответа
Это запутанная тема. Проблема не в том коде, который вы опубликовали. Это код, который вы не опубликовали. Это код, который сгенерировал df_out
Рассмотрите этот пример и обратите внимание на последнюю строку, которая генерирует предупреждение.
df_other = pd.DataFrame(dict(A=[1], B=[2]))
df_out = df_other[:]
df_out['E'] = 5
//anaconda/envs/3.5/lib/python3.5/site-packages/ipykernel/__main__.py:4: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
Теперь мы попробуем эквивалентную вещь, которая не выдаст предупреждение
df_other = pd.DataFrame(dict(A=[1], B=[2]))
df_out = df_other.loc[:]
df_out['E'] = 5
затем
print `df_out`
A B E
0 1 2 5
Это сводится к пандам, решающим прикрепить is_copy
Атрибут для фрейма данных, когда он построен на основе множества критериев.
Обратите внимание на
df_other[:].is_copy
<weakref at 0x103323458; to 'DataFrame' at 0x116a684e0>
когда
df_other.loc[:].is_copy
Возвращает None
Итак, какие типы конструкции запускают копию? Я до сих пор не знаю всего, и даже вещи, которые я знаю, не имеют смысла для меня.
Например, почему это не срабатывает?
df_other[['A', 'B', 'E']].is_copy
Во-первых, я не уверен, что это эффективный или лучший подход. Однако у меня возникла та же проблема, когда я добавлял новый столбец в существующий фрейм данных, и я решил использовать метод reset_index.
Здесь я сначала отбрасываю строки Nan из столбца EMPLOYEES и назначаю этот управляемый фрейм данных новому фрейму данных df1, а затем добавляю столбец COMPANY_SIZE к df1 следующим образом:
df1 = all_merged_years.dropna(subset=['EMPLOYEES']).reset_index()
column = df1['EMPLOYEES']
Size =[]
df1['COMPANY_SIZE'] = ' '
for number in column:
if number <=999:
Size.append('Small')
elif 999<number<=9999:
Size.append('Medium')
elif 9999<number:
Size.append('Large')
else:
Size.append('UNKNOWN')
df1['COMPANY_SIZE'] = Size
Таким образом, я НЕ получил предупреждение как таковое. Надеюсь, это поможет.