在函数内使用Pandas extract()触发SettingWithCopyWarning如何解决
Pandas函数内操作过滤后DataFrame触发SettingWithCopyWarning的解决方案
问题原因
该警告由Pandas 0.23版本的链式赋值检测逻辑导致:
- 过滤操作返回的结果在旧版本Pandas中会被标记为原DataFrame的潜在视图
- 函数内部作用域下,Pandas的副本检测逻辑更严格,会误判你对过滤后df的列修改是在操作原df的切片,因此触发警告
- 全局作用域下副本检测阈值更低,所以相同代码在函数外运行不会触发警告
最优解决方案
在过滤操作后显式调用.copy(),明确告诉Pandas当前对象是独立的新副本,彻底规避检测误报。同时可以优化正则表达式,精准匹配两个短横线之间的6位reportId:
def test_extract(df): # 先复制原df,避免修改传入的原始对象 df_process = df.copy() df_process['date'] = pd.to_datetime(df_process['date_unix'], unit='s') # 过滤后显式copy,确认是独立对象 df_process = df_process.loc[df_process['date'] >= pd.to_datetime('2021-09-23'), :].copy() # 优化正则,精准匹配两段短横线之间的6位字符 df_process['reportId'] = df_process['id'].str.extract(r"-([a-zA-Z0-9]{6})-") return df_process
其他可选方案
方案1:直接在原df上用.loc操作,避免中间切片赋值
如果你不需要保留原df的原始内容,可以直接基于布尔掩码操作,不会触发警告:
def test_extract(df): df['date'] = pd.to_datetime(df['date_unix'], unit='s') mask = df['date'] >= pd.to_datetime('2021-09-23') # 直接用.loc指定行和列赋值,不会触发切片检测 df.loc[mask, 'reportId'] = df.loc[mask, 'id'].str.extract(r"-([a-zA-Z0-9]{6})-") return df.loc[mask, :]
方案2:临时关闭警告(不推荐)
如果你确认自己的操作逻辑没有问题,可以临时关闭链式赋值警告,用完后恢复即可:
import pandas as pd def test_extract(df): # 临时关闭警告并保存原始设置 original_setting = pd.options.mode.chained_assignment pd.options.mode.chained_assignment = None df['date'] = pd.to_datetime(df['date_unix'], unit='s') df = df.loc[df['date'] >= pd.to_datetime('2021-09-23'),:] df['reportId'] = df['id'].str.extract(r"-([a-zA-Z0-9]{6})-") # 恢复原始设置 pd.options.mode.chained_assignment = original_setting return df
内容的提问来源于stack exchange,提问作者Austin
相关产品推荐
相关产品推荐

