SettingWithCopyWarning 解决方案
问题场景:我在读取csv文件之后,因为要新增一个特征列并根据已有特征修改新增列的值,结果在修改的时候就碰到了SettingWithCopyWarning这个警告,花了很长时间才解决这个问题。
一个简易版的范例
import pandas as pd
import numpy as np
aa = np.array([1, 0, 1, 0])
bb = pd.DataFrame(aa.T, columns=['one'])
print(bb)
输出为:
one
0 1
1 0
2 1
3 0
添加一个新列后在输出
bb['two'] = 0
print(bb)
output[]:
one two
0 1 0
1 0 0
2 1 0
3 0 0
按条件修改新列再输出就报错了:
for i in range(bb.shape[0]):
if bb['one'][i] == 0:
bb['two'][i] = 1
print(bb)
output[]:
C:/PycharmProjects/NaiveBayesProduct/pandas/try_index.py:22: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame
See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
bb['two'][i] = 1
one two
0 1 0
1 0 1
2 1 0
3 0 1
这个问题怎么解决呢,我查了stackoverflow上的很多帖子,试了loc/iloc等函数都不管用,最后才发现是顺序错了。正确方案应该是生成好正确的数组再插入dataframe中。下面我把上面的例子用正确地方法再重新生成一遍。
import pandas as pd
import numpy as np
aa = np.array([1, 0, 1, 0])
bb = pd.DataFrame(aa.T, columns=['one'])
# 生成一个ndarray,装要插入的值
two = np.zeros(bb.shape[0])
# 按条件修改two
for i in range(bb.shape[0]):
if bb['one'][i] == 0:
two[i] = 1
# 完成后将two插入dataframe中
bb.insert(1,'two', two)
print(bb)
output[]:
one two
0 1 0.0
1 0 1.0
2 1 0.0
3 0 1.0
就OK了,如果你也遇到相似的问题可以使用我这种办法解决。