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

Таким образом, я НЕ получил предупреждение как таковое. Надеюсь, это поможет.

Другие вопросы по тегам