Путаница в отношении: копия панда предупреждение о кадре данных

Я просмотрел кучу вопросов и ответов, связанных с этой проблемой, но все еще обнаруживаю, что получаю эту копию предупреждения о срезах в местах, где я этого не ожидаю. Кроме того, он появляется в коде, который раньше работал нормально для меня, что заставляет меня задуматься о том, может ли какое-то обновление быть виновником.

Например, это набор кода, где все, что я делаю, это чтение в файле Excel в пандыDataFrameи вырезать набор столбцов, включенных вdf[[]] синтаксис.

 izmir = pd.read_excel(filepath)
 izmir_lim = izmir[['Gender','Age','MC_OLD_M>=60','MC_OLD_F>=60','MC_OLD_M>18','MC_OLD_F>18','MC_OLD_18>M>5','MC_OLD_18>F>5',
               'MC_OLD_M_Child<5','MC_OLD_F_Child<5','MC_OLD_M>0<=1','MC_OLD_F>0<=1','Date to Delivery','Date to insert','Date of Entery']]

Теперь любые дальнейшие изменения, которые я делаю в этомizmir_lim файл поднять копию среза предупреждение.

izmir_lim['Age'] = izmir_lim.Age.fillna(0)
izmir_lim['Age'] = izmir_lim.Age.astype(int)

/Users/samlilienfeld/anaconda/lib/python3.5/site-packages/ipykernel/главный.py: 2: SettingWithCopyWarning: пытается установить значение для копии среза из DataFrame. Попробуйте вместо этого использовать .loc [row_indexer, col_indexer] = значение

Я в замешательстве, потому что я думал, чтоdf[[]] Подмножество столбцов вернуло копию по умолчанию. Единственный способ, который я нашел для подавления ошибок, это явное добавлениеdf[[]].copy(), Я мог поклясться, что в прошлом мне не нужно было этого делать, и я не поднял копию ошибки среза.

Точно так же у меня есть некоторый другой код, который выполняет функцию на фрейме данных, чтобы фильтровать его определенным образом:

def lim(df):
if (geography == "All"):
    df_geo = df
else:
    df_geo = df[df.center_JO == geography]

df_date = df_geo[(df_geo.date_survey >= start_date) & (df_geo.date_survey <= end_date)]

return df_date

df_lim = lim(df)

С этого момента, любые изменения, которые я делаю в любое из значенийdf_lim поднять копию ошибки среза. Единственный способ обойти это, что я нашел, это изменить вызов функции на:

df_lim = lim(df).copy()

Это просто кажется мне неправильным. Что мне не хватает? Кажется, что эти варианты использования должны возвращать копии по умолчанию, и я мог поклясться, что в последний раз, когда я запускал эти сценарии, я не запускал эти ошибки.
Мне просто нужно начать добавлять.copy() повсюду? Похоже, должен быть более чистый способ сделать это. Любое понимание или помощь очень ценится.

 ayhan08 авг. 2016 г., 19:49
Это предупреждение действует как напоминание о том, чтоizmir_lim это копия. Изменения, которые вы делаете вizmir_lim не будет отражено вizmir, Вы не делаете ничего плохого. Вы можете установитьizmir_lim.is_copy = None избавиться от предупреждения.

Ответы на вопрос(1)

Решение Вопроса
 izmir = pd.read_excel(filepath)
 Gender','Age','MC_OLD_M>=60','MC_OLD_F>=60',
                    'MC_OLD_M>18','MC_OLD_F>18','MC_OLD_18>M>5',
                    'MC_OLD_18>F>5','MC_OLD_M_Child<5','MC_OLD_F_Child<5',
                    'MC_OLD_M>0<=1','MC_OLD_F>0<=1','Date to Delivery',
                    'Date to insert','Date of Entery']]

izmir_lim это вид / копияizmir, Вы впоследствии пытаетесь присвоить ему. Это то, что выдает ошибку. Используйте это вместо:

 ;Gender','Age','MC_OLD_M>=60','MC_OLD_F>=60',
                    'MC_OLD_M>18','MC_OLD_F>18','MC_OLD_18>M>5',
                    'MC_OLD_18>F>5','MC_OLD_M_Child<5','MC_OLD_F_Child<5',
                    'MC_OLD_M>0<=1','MC_OLD_F>0<=1','Date to Delivery',
                    'Date to insert','Date of Entery']].copy()

Всякий раз, когда вы «создаете» новый фрейм данных из другого следующим образом:

new_df = old_df[list_of_columns_names]

new_df будет иметь истинное значение в этомis_copy приписывать. Когда вы пытаетесь присвоить ему, панды бросаетSettingWithCopyWarning.

new_df.iloc[0, 0] = 1  # Should throw an error

Вы можете преодолеть это несколькими способами.

Опция 1
new_df = old_df[list_of_columns_names].copy()
Вариант № 2 (как @ayhan предложил в комментариях)
new_df = old_df[list_of_columns_names]
new_df.is_copy = None
Вариант № 3
new_df = old_df.loc[:, list_of_columns_names]
 EliadL10 дек. 2018 г., 15:46
Варианты № 1 (df[cols].copy()) и № 3 (df.loc[:, cols]) оба могут работатьно они делают разные вещи. В то время как первый делает копию, последний обеспечивает прямой фрагмент исходного кадра данных. Таким образом, использование # 3 для изменения значения также изменит исходный фрейм данных, тогда как использование # 1 - нет.
 Sam Lilienfeld11 авг. 2016 г., 13:21
Я все еще продолжаю сталкиваться с этой ошибкой в ​​замешательстве, даже когда использую.loc индексировать в кадры данных. Например, я создаю отфильтрованный фрейм данных, который удаляет строки с нулевыми значениями следующим образом:df_no_none = df_trans.loc[df_trans.value.notnull()], Я продолжаю получать копию ошибок среза каждый раз, когда я манипулируюdf_no_none, Есть идеи?
 gseattle29 нояб. 2017 г., 05:14
В Pandas было бы полезно, если бы они поменяли это на более удобный английский: для копии среза из DataFrame было установлено значение, в том числе из-за того, что он не просто пытается, а успешно. :>
 Sam Lilienfeld08 авг. 2016 г., 19:56
Можете ли вы помочь мне понять логику необходимости этого? Является ли izmir_lim отдельным фреймом данных или представлением подмножества izmir? И если это просто вид, почему панды настроены так? В моих рабочих процессах я всегда хотел бы создать полностью отдельный фрейм данных, как только я подмножество, и смогу манипулировать отфильтрованным фреймом данных, как мне угодно. Я думаю, просто кажется, что требование .copy () повсеместно просто не должно быть необходимым, но, возможно, я просто не понимаю другие варианты использования.
 piRSquared08 авг. 2016 г., 20:01
@SamLilienfeld pandas настроен на работу таким образом, чтобы максимально эффективно использовать память. Если вы всегда хотите создать новый независимый фрейм данных, используйте один из вариантов, и он у вас будет. Я замечаю это, только когда создаю подмножество черезold_df[list_O_cols], Часто яold_df.loc[:, list_O_cols] и у меня нет проблем. Это теперь вариант 3.
 piRSquared11 авг. 2016 г., 14:47
Попробуйте прочитатьstackoverflow.com/a/38147527/2336654
 Sam Lilienfeld08 авг. 2016 г., 20:09
Ницца.loc подход работает отлично, как и другие. Все еще нахожу свой путь вокруг.loc, .ix индексаторы и т. д. не всегда были ясны, какой из них является правильным в данном контексте. Отчасти я думаю, потому что имена немного загадочные. Огромное спасибо!!

Ваш ответ на вопрос