Pandas系列教程(7)Pandas的SettingWithCopyWarning

Pandas的SettingWithCopyWarning

1、读取数据

import pandas as pd

file_path = "../datas/files/beijing_tianqi_2018.csv"
df = pd.read_csv(file_path)

# 替换温度的后缀℃, 并转为int32(修改列)
df.loc[:, 'bWendu'] = df.loc[:, 'bWendu'].str.replace('', '').astype('int32')
df.loc[:, 'yWendu'] = df.loc[:, 'yWendu'].str.replace('', '').astype('int32')

print(df.head(3))

 

2、复现

import pandas as pd

file_path = "../../datas/files/beijing_tianqi_2018.csv"
df = pd.read_csv(file_path)

# 替换温度的后缀℃, 并转为int32(修改列)
df.loc[:, 'bWendu'] = df.loc[:, 'bWendu'].str.replace('', '').astype('int32')
df.loc[:, 'yWendu'] = df.loc[:, 'yWendu'].str.replace('', '').astype('int32')
print('*' * 25, '替换温度的后缀,并转为int类型', '*' * 25)
print(df.head(3))

# 只选出3月份的数据用于分析
condition = df['ymd'].str.startswith('2018-03')
print('*' * 25, '只选出3月份的数据用于分析', '*' * 25)
print(condition)

# 设置温差
print('*' * 25, '设置温差', '*' * 25)
df[condition]['wen_cha'] = df['bWendu'] - df['yWendu']

# 查看是否修改成功
print('*' * 25, '查看是否修改成功', '*' * 25)
print(df[condition].head())

运行结果:

************************* 替换温度的后缀,并转为int类型 *************************
          ymd  bWendu  yWendu tianqi fengxiang fengli  aqi aqiInfo  aqiLevel
0  2018-01-01       3      -6   晴~多云       东北风   1-2级   59       良         2
1  2018-01-02       2      -5   阴~多云       东北风   1-2级   49       优         1
2  2018-01-03       2      -5     多云        北风   1-2级   28       优         1
************************* 只选出3月份的数据用于分析 *************************
0      False
1      False
2      False
3      False
4      False
       ...  
360    False
361    False
362    False
363    False
364    False
Name: ymd, Length: 365, dtype: bool
************************* 设置温差 *************************
************************* 查看是否修改成功 *************************
           ymd  bWendu  yWendu tianqi fengxiang fengli  aqi aqiInfo  aqiLevel
59  2018-03-01       8      -3     多云       西南风   1-2级   46       优         1
60  2018-03-02       9      -1   晴~多云        北风   1-2级   95       良         2
61  2018-03-03      13       3   多云~阴        北风   1-2级  214    重度污染         5
62  2018-03-04       7      -2   阴~多云       东南风   1-2级  144    轻度污染         3
63  2018-03-05       8      -3      晴        南风   1-2级   94       良         2
F:/Python_Projects/PythonDataAnalysis/4_Pandas/8_Pandas的SettingWithCopyWarning/8.1 复现/demo.py:19: 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[condition]['wen_cha'] = df['bWendu'] - df['yWendu']
原因:
发出警告的代码 df[condition]['wen_cha'] = df['bWendu'] - df['yWendu']
相当于:df.get(condition).set(wen_cha), 第一步骤的get发出了警报
链式操作确实是两个步骤,先get后set,get得到的dataframe可能是view也可能是copy,pandas发出警告
核心要诀:pandas的dataframe的修改写操作,只允许在源dataframe上进行,一步到位

3、解决

解决方式1

import pandas as pd

file_path = "../../datas/files/beijing_tianqi_2018.csv"
df = pd.read_csv(file_path)

# 替换温度的后缀℃, 并转为int32(修改列)
df.loc[:, 'bWendu'] = df.loc[:, 'bWendu'].str.replace('', '').astype('int32')
df.loc[:, 'yWendu'] = df.loc[:, 'yWendu'].str.replace('', '').astype('int32')
print('*' * 25, '替换温度的后缀,并转为int类型', '*' * 25)
print(df.head(3))

# 只选出3月份的数据用于分析
condition = df['ymd'].str.startswith('2018-03')
print('*' * 25, '只选出3月份的数据用于分析', '*' * 25)
print(condition)

# 设置温差
print('*' * 25, '设置温差', '*' * 25)
# 将get + set的两步操作,改成set的一步操作
df.loc[condition, 'wen_cha'] = df['bWendu'] - df['yWendu']

# 查看是否修改成功
print('*' * 25, '查看是否修改成功', '*' * 25)
print(df[condition].head())

解决方式2

import pandas as pd

file_path = "../../datas/files/beijing_tianqi_2018.csv"
df = pd.read_csv(file_path)

# 替换温度的后缀℃, 并转为int32(修改列)
df.loc[:, 'bWendu'] = df.loc[:, 'bWendu'].str.replace('', '').astype('int32')
df.loc[:, 'yWendu'] = df.loc[:, 'yWendu'].str.replace('', '').astype('int32')
print('*' * 25, '替换温度的后缀,并转为int类型', '*' * 25)
print(df.head(3))

# 只选出3月份的数据用于分析
condition = df['ymd'].str.startswith('2018-03')
print('*' * 25, '只选出3月份的数据用于分析', '*' * 25)
print(condition)

# 设置温差
# 如果需要预筛选数据做后续的处理分析,使用copy赋值dataframe
print('*' * 25, '设置温差', '*' * 25)
df_month3 = df[condition].copy()
print(df_month3.head())
df_month3['wen_cha'] = df['bWendu'] - df['yWendu']

# 查看是否修改成功
print('*' * 25, '查看是否修改成功', '*' * 25)
print(df[condition].head())

总而言之,pandas不允许先筛选子dataframe,再进行修改写入

要么使用.loc实现一个步骤直接修改源dataframe

要么先复制一个子dataframe再一个步骤执行修改

 

原文地址:https://www.cnblogs.com/xingxingnbsp/p/13851834.html