почему я получаю SettingWithCopyWarning от pandas

#python #python-3.x #pandas

#python #python-3.x #pandas

Вопрос:

Я рассмотрел некоторые вопросы, касающиеся этого предупреждения, и все еще немного сбит с толку. Мой метод выглядит следующим образом:

     def _apply_standard_filters(self, df: pd.DataFrame) -&&t; pd.DataFrame:
        lo&&er.info("Applyin& standard filters")
        df["Type"] = df["Type"].apply(lambda x: x.strip().lower())

        df = df[df.Type == "xxxx"]

        df = df[df['Other Column'].str.contains(r"some_re&ex", na=False, re&ex=True)]

        return df

  

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

         df["Type"] = df["Type"].str.strip()
        df["Type"] = df["Type"].str.lower()
  

Я подумал, может быть, это связано с присвоением дважды одного и того же столбца, поэтому я переписал, чтобы использовать apply (как в 1-м фрагменте). Все еще получаю то же предупреждение. Наконец, я снова переписал с loc, вот так:

 df["Type"] = df.loc[:, "Type"].apply(lambda x: x.strip().lower())
  

и предупреждение все еще там. Чего мне здесь не хватает?

Также вот результат, который я получаю

 2020-08-12 15:38:14,498 - filters - INFO - Applyin& standard filters
filters.py:16: Settin&WithCopyWarnin&:
A value is tryin& to be set on a copy of a slice from a DataFrame.
Try usin& .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.or&/pandas-docs/stable/user_&uide/indexin&.html#returnin&-a-view-versus-a-copy
  df["Type"] = df.loc[:, "Type"].apply(lambda x: x.strip().lower())
  

Возможно, это связано с чем-то, что я делаю перед вызовом этого метода? Я использую это _apply_standard_filters() всегда, после того, как я использую другой метод фильтрации в зависимости от выбора пользователя. Однако я никогда не касаюсь типа или другого столбца перед стандартными фильтрами. обычно это выглядит так:

 df = df[df.Column1.str.contains(r"some other re&ex pattern", na=False, re&ex=True)]
df = self._apply_standard_filters(df=df)
  

Приветствуются любые предложения.

Приветствия!

Редактировать

После ответа @r.ook я применил его решение, просто немного исправил его и все еще получаю то же предупреждение перед моим лицом. Теперь код выглядит следующим образом:

 def _apply_standard_filters(self, df: pd.DataFrame) -&&t; pd.DataFrame:
    lo&&er.info("Applyin& standard filters")
    df["Type"] = df.loc[:, "Type"].apply(lambda x: x.strip().lower())

    df = df.loc[df.Type == "xxxx"]

    df = df.loc[df['Other Column'].str.contains(r"some_re&ex", na=False, re&ex=True)]

    df = df[df['Other Column'].str.contains(r"some_re&ex", na=False, re&ex=True)]

    return df

def filter_somethin&(self, df: pd.DataFrame) -&&t; pd.DataFrame:
    df = df.loc[df.Column1.str.contains(r"^Some re&ex", na=False, re&ex=True)]
    df = self._apply_standard_filters(df=df)
    return df
  

Когда я запускаю это, я все еще получаю:

 filters.py:17: Settin&WithCopyWarnin&:
A value is tryin& to be set on a copy of a slice from a DataFrame.
Try usin& .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: http://pandas.pydata.or&/pandas-docs/stable/user_&uide/indexin&.html#returnin&-a-view-versus-a-copy
  df["Type"] = df.loc[:, "Type"].apply(lambda x: x.strip().lower())
  

Должен ли я сосредоточиться на этой конкретной строке, упомянутой в предупреждении? Я раньше не видел этого предупреждения. Оно появилось, когда я добавил strip() и lower() в df["Type"] . Когда я запускаю код без этой строки, предупреждения нет, независимо от изменений, которые я внес в другие назначения df.

Ответ №1:

Всякий раз, когда у вас есть строки, которые выглядят следующим образом, df = df[...] это вызовет Settin&WithCopyWarnin& .

Судя по последнему вашему вопросу, похоже, что вы уже передаете копию в метод, вот почему срабатывает предупреждение.

Сделайте это вместо:

 df = df.loc[:, df.Column1.str.contains(r"some other re&ex pattern", na=False, re&ex=True)]
df = self._apply_standard_filters(df=df)
  

Аналогичным образом отредактируйте все строки в вашем методе, которые следуют одному и тому же df = df[...] шаблону:

     df = df.loc[:, df.Type == "xxxx"]
    df = df.loc[:, df['Other Column'].str.contains(r"some_re&ex", na=False, re&ex=True)]
  

Комментарии:

1. Невозможно разбивать строки в комментариях, поэтому 🙂 Вышеописанное не сработает, оно сгенерирует невыравниваемый логический ряд, предоставленный в качестве индексатора (индекс логического ряда и индексированного объекта не совпадают). Это должно больше походить на df.loc[ df. Type == «vuln» ] Однако я раньше не сталкивался с оригинальным предупреждением в этом скрипте. И я всегда использовал шаблон df = df […]

2.Я имел в виду, что когда у вас есть df = df[...] шаблон, он не немедленно вызовет предупреждение, но любое последующее назначение / изменения df будут вызывать предупреждение.

3. Я избавился от этого шаблона, df = df[...] все еще получая предупреждение, когда это существует df["Type"] = df.loc[:, "Type"].apply(lambda x: x.strip().lower()) . Если я удалю эту строку, предупреждения не будет, даже если я вернусь к df = df[...] шаблону в других строках