为啥我从熊猫那里得到 SettingWithCopyWarning

Posted

技术标签:

【中文标题】为啥我从熊猫那里得到 SettingWithCopyWarning【英文标题】:why am I getting SettingWithCopyWarning from pandas为什么我从熊猫那里得到 SettingWithCopyWarning 【发布时间】:2020-12-02 07:15:20 【问题描述】:

我遇到了一些关于这个警告的问题,但仍然有点困惑。我的方法如下:

    def _apply_standard_filters(self, df: pd.DataFrame) -> pd.DataFrame:
        logger.info("Applying 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_regex", na=False, regex=True)]

        return df

我收到了关于带有 lambda 函数的那条行的警告。最初,当线条如下所示时,我收到了警告:

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

我认为这可能与分配两次相同的列有关,所以我重写以使用 apply(如在第一个 sn-p 中)。仍然收到相同的警告。最后我又用 loc 重写了一遍,像这样:

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

并且警告仍然存在。我在这里错过了什么?

这也是我得到的输出

2020-08-12 15:38:14,498 - filters - INFO - Applying standard filters
filters.py:16: 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: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-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 regex pattern", na=False, regex=True)]
df = self._apply_standard_filters(df=df)

欢迎提出任何建议。

干杯!

编辑

在@r.ook 回答后,我应用了他的解决方案,只是稍微修复了一点,但在我面前仍然有同样的警告。现在代码如下所示:

def _apply_standard_filters(self, df: pd.DataFrame) -> pd.DataFrame:
    logger.info("Applying 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_regex", na=False, regex=True)]

    df = df[df['Other Column'].str.contains(r"some_regex", na=False, regex=True)]

    return df

def filter_something(self, df: pd.DataFrame) -> pd.DataFrame:
    df = df.loc[df.Column1.str.contains(r"^Some regex", na=False, regex=True)]
    df = self._apply_standard_filters(df=df)
    return df

当我运行它时,我仍然得到:

filters.py:17: 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/user_guide/indexing.html#returning-a-view-versus-a-copy
  df["Type"] = df.loc[:, "Type"].apply(lambda x: x.strip().lower())

我应该关注警告中提到的这一特定行吗?我以前没见过这个警告。它出现在我将strip()lower() 添加到df["Type"] 时。当我在没有该行的情况下运行代码时,无论我在其他 df 分配中所做的更改如何,都没有警告。

【问题讨论】:

【参考方案1】:

只要你有类似df = df[...] 的行,它就会触发SettingWithCopyWarning

从您的最后一个问题来看,您似乎已经将副本传递给该方法,这就是触发警告的原因。

改为这样做:

df = df.loc[:, df.Column1.str.contains(r"some other regex pattern", na=False, regex=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_regex", na=False, regex=True)]

【讨论】:

不可能在 cmets 中换行,所以 :) 上面不起作用,它会生成作为索引器提供的不可对齐的布尔系列(布尔系列的索引和索引对象的索引不匹配)。它应该看起来更像 df.loc[ df.Type == "vuln" ] 但是,我之前在这个脚本中没有遇到过原始警告。而且我总是使用 df = df[...] 模式 我的意思是,当你有df = df[...] 模式时,它不会立即 触发警告,而是任何后续分配/更改df 将触发警告。 我摆脱了这种模式df = df[...] 当它存在时仍然收到警告df["Type"] = df.loc[:, "Type"].apply(lambda x: x.strip().lower())。如果我删除该行,即使我在其他行中返回 df = df[...] 模式,也不会发出警告

以上是关于为啥我从熊猫那里得到 SettingWithCopyWarning的主要内容,如果未能解决你的问题,请参考以下文章

为啥添加innerHTML后循环和数组停止工作?

vbscript 第2部分我从安德鲁那里得到的代码是进出excel和/或进出的代码

vbscript 第2部分我从安德鲁那里得到的代码是进出excel和/或进出的代码

我从别人那里拷贝来一个c#的项目,但是没有拷贝数据库文件。为啥这个项目也能正常增删改查?

为啥我需要日期格式? [关闭]

为啥我从这个查询中得到无效号码?