pandas警告:SettingWithCopyWarning

  在使用pandas对DataFrame进行赋值操作时,会出现一个看似莫名巧妙的告警信息:

  SettingWithCopyWarning:A value is trying to be set on a copy of slice from a DataFrame

  Try using .loc[row_indexer,col_indexer] = value instead

  这条告警信息的大意是,“尝试在DataFrame一个切片的副本上进行赋值,使用 .loc[row_indexer,col_indexer] = value 代替当前赋值操作”。导致这条告警产生的原因,是由于pandas无法判断对原始DataFrame进行切片,产生的是视图还是副本。如果切片产生的是视图,则赋值操作会修改原始DataFrame,如果产生的是副本,则不会修改原始的DataFrame。

  一般产生这条告警,都是由于使用链式索引(chained indexing)赋值导致的;而使用  .loc[row_indexer,col_indexer] 则会产生一个新的DataFrame,在某些情况下,可以解决该告警问题(ps:导致 SettingWithCopyWarning 告警产生的情况不止一种!)。如果你选择忽视这条告警,那么你最好查看一下自己的赋值操作有没有成功(虽然本人实际运用中查看了多次,都是成功的,但不代表每一次都能成功,所以建议还是不要忽视这条告警)。

 

# 下面的操作就会出现SettingWithCopyWarning警告
df_select = df[df['col_name]>value]   # 通过条件筛选,得到df_select
# 假设此时我们想修改df_select列 'col'的值:
df_select['col']  = new_value
# 此时就会出现SettingWithCopyWarning,因为df_select 发生改变,pandas无法判断原始df究竟会不会改变
# 实际上上述过程就用了链式索引进行赋值,上述过程等价于:
 df[df['col_name]>value]['col']  = new_value
# 解决这个问题比较好的一个方法是手动进行复制:
df_select = df[df['col_name]>value].copy()  # 这样df_select是df的一个复本,df_select的改变也不会影响df

  

  总而言之,应该竟可能的避免使用链式索引对 DataFrame 进行赋值操作。更多产生告警的原因及解决方法的详解,可以参考pandas官方文档中的 "Indexing and Selecting Data"模块下的"Returning a view versus a copy"  http://pandas.pydata.org/pandas-docs/stable/indexing.html#returning-a-view-versus-a-copy。也可参考我看到一篇写的很好的文章:https://www.dataquest.io/blog/settingwithcopywarning/(英文原文),https://www.jianshu.com/p/72274ccb647a(中文翻译版)。

posted @ 2018-10-22 15:58  Solong1989  阅读(7956)  评论(0编辑  收藏  举报