如何解决 Pandas 中的 SettingwithCopyWarning 警告

一、SettingWithCopyWarning 是什么?

在使用 numpy 和 pandas 的过程当中,如果使用向量化的方法来回测的话,由于经常需要用到赋值操作,很多的操作都会触发 SettingWithCopyWarning 的警告

“ 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 ”

给这个警告搞得不胜其烦,所以好好研究一下,到底应该怎么解决这个问题。
在 pandas 的一些操作中,有的时候会返回一个 view of data 而有一些会返回一个 copy.
view 和 copy 的区别如下图所示:
View 和 Copy 的区别
如上图所示:如果是 df2 是view 的话,实际上df2是df1的一个子集,而如果df2是copy的话,实际上df1和df2是两个完全不同的 DataFrame。

所以当我们尝试去改变df2的值的时候,我们会发现:修改view和修改copy,会得到完全不同的结果,因此 pandas就会出现警告。
修改view和修改copy的区别

二、解决办法

1.直接关闭 Warning

直接在pandas关闭warning:

import warnings
import pandas as pd
from pandas.core.common import SettingWithCopyWarning

warnings.simplefilter(action="ignore", category=SettingWithCopyWarning)

df = pd.DataFrame(dict(A=[1, 2, 3], B=[2, 3, 4]))
df[df['A'] > 2]['B'] = 5

2.使用copy来更改

我们先来看一下一般是什么时候出现 SettingWithCopyWarning。下图是 300905.SZ 的 2021年未复权的K线图,可以看到在2021年5月17日之后复权有一个跳空,因此在计算的时候,需要乘上一个复权因子。
在这里插入图片描述
我们先把数据取出来看一看

year_lst = ['2021']
data_dic = assistant.ReadDayBarYear(year_lst=year_lst)
stock_name = '300905.SZ'
df = data_dic[stock_name][['Open','High','Low','Close','Volume','Adj_Factor']]
tmp_df = df.loc['20210515':'20210520']
print(tmp_df)

在这里插入图片描述
现在对开盘价复权

df['Open'] = df['Open']*df['Adj_Factor']

则此时即会发出警告:
这时候我们再看

tmp_df = df.loc['20210515':'20210520']
print(tmp_df)

在这里插入图片描述
可以看到此时的开盘价已经改变
由上面的分析可以看出,由于df是 data_dic 的一个 view 因此我们在改变df的值的时候,pandas 就会疑惑,到底是连data_dic 中的数据也改变呢?还是只改变 df 中的值呢?因此我们让df成为 data_dic 的一个copy,这样子就不会出现 warning 了

import copy
year_lst = ['2021']
data_dic = assistant.ReadDayBarYear(year_lst=year_lst)
stock_name = '300905.SZ'
df = copy.copy(data_dic[stock_name][['Open','High','Low','Close','Volume','Adj_Factor']])
# 此时给价格复权,就不会有警告了
df['Open'] = df['Open']*df['Adj_Factor']
tmp_df = df.loc['20210515':'20210520']
print(tmp_df)

总结

不得不说出现这个warning的时候,下面的一句话很具有迷惑性:
“ Try using .loc[row_indexer,col_indexer] = value instead ”
最开始的时候,还想尝试使用 df.loc 来解决问题,结果怎么搞都不行。

另外在给 DataFrame 的单独的行列赋值的时候,这个问题也会导致出现赋值失败的情况,这个等下一次有机会的时候再讨论吧。

  • 22
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值