0. 如何解决
简单来说就是加个 .copy() 即可
也就是强制让pandas给某个dataframe创建一个副本,表明我绝对是在新的一个dataframe上操作,而不是在原有的dataframe上操作
下面举例如何复现这个警告,然后说明下为什么出现这个警告,最后会给出一个解决方法来解决这个警告
1. 如何复现如下警告(运行如下代码将会出现SettingWithCopyWarning这个警告)
# 首先引入pandas这个库是必须的 import pandas as pd # 然后建一个简单的DataFrame来举例说明 df = pd.DataFrame({'c1':[1,2,3], 'c2':[100,200,300]}) # 可以将这个简单的DataFrame打印出来看看是个什么样子 print('df:\n', df) # 接下来,简单地复现这个警告 # 也就是取出df的'c1'这一列,然后改变其第2行的值即可 df1 = df[['c1']] df1['c1'][1] = 0 # 在改变df1的c1列的第2行后,将会出现类似下面的警告: # Warning (from warnings module): # File ......一些信息...... # SettingWithCopyWarning: # A value is trying to be set on a copy of a slice from a DataFrame # See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
# 当然,可以打印一下df1,看看现在的df1有何变化(注:成功改变了这个df1中的值,没有改变df中的值)
print('df1:\n', df1)
2. 解释说明为什么执行上述代码后会出现SettingWithCopyWarning这个警告
因为pandas不知道你是想在原有的df上的第c1列进行操作(影响原有的df)
还是想提取出c1这一列并复制一份副本,然后在这个副本上进行操作(不影响原有的df)
扫描二维码关注公众号,回复:
11158169 查看本文章
3. 解决办法,加一个.copy(),表面我想提取出c1这一列并复制一份副本,然后在这个副本上进行操作(不影响原有的df)
# 首先,删除上面的三句代码
df1 = df[['c1']]
df1['c1'][1] = 0
print('df1:\n', df1)
# 然后
# 加一个copy()就行,表明我绝对是在新的一个dataframe上操作,而不是在原有的dataframe上操作 # copy()就是强制让pandas创建一个副本 df2 = df[['c1']].copy() # 现在改变c1列的第2行的值,就不会出现SettingWithCopyWarning这个警告了 df2['c1'][1] = 0
4. 完整的不出现警告的代码
import pandas as pd df = pd.DataFrame({'c1':[1,2,3], 'c2':[100,200,300]}) print('df:\n', df) # 用.copy() df1 = df[['c1']].copy() df1['c1'][1] = 0 print('df1:\n', df1)