我有两个数据框。两者都具有相同的列集,但某些列是分类类型的(基于实际包含的值)。为了将它们组合起来,我使用两个值的并集刷新分类列的分类类型。
def appendDFsWithCat(df1, df2):
columns = df1.select_dtypes(include=['category']).columns
for c in columns:
catValues1 = list(df1[c].cat.categories)
catValues2 = list(df2[c].cat.categories)
catValues = list(set(catValues1 + catValues2))
df1[c] = df1[c].cat.set_categories(catValues)
df2[c] = df2[c].cat.set_categories(catValues)
return df1.append(df2, ignore_index=True).reset_index(drop=True)
一切都按预期进行,但我想了解为什么执行此代码时会引发SettingWithCopyWarning:
df1[c] = df1[c].cat.set_categories(catValues)
Utility.py:149: SettingWithCopyWarning:
我发现除了使用过的类别数据之外,没有其他可能刷新类别数据。
这很可能是由于您传递给函数的对象而发生的。
如果我设置以下示例:
cats1 = pd.Series(['a', 'a', 'b', 'b'], name='cat', dtype="category")
data1 = pd.Series([1, 2, 3, 4], name='val', dtype=np.int64)
df1 = pd.concat([cats1, data1], axis=1)
并运行你的函数:
print appendDFsWithCat(df1, df1)
我没有收到错误,并且输出:
cat val
0 a 1
1 a 2
2 b 3
3 b 4
4 a 1
5 a 2
6 b 3
7 b 4
但是,如果我运行这个:
print appendDFsWithCat(df1.iloc[:-1], df1)
我收到以下警告:
C:\Anaconda2\lib\site-packages\ipykernel\__main__.py:7: 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: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
这个输出:
cat val
0 a 1
1 a 2
2 b 3
3 a 1
4 a 2
5 b 3
6 b 4
如果您阅读该警告,它会告诉您正在尝试在作为另一个对象的切片或 View 的对象上设置值。这意味着您在特定位置分配值的数据框只是对另一个对象的引用。我通过将数据帧传递给我知道是切片或 View 的函数来制造这种情况。
您可以通过强制对象成为它们自己的东西来解决这个问题,如下所示:
解决方案
<小时/>
def appendDFsWithCat(df1, df2):
# I added this line to ensure they are their own dataframes
df1, df2 = df1.copy(), df2.copy()
columns = df1.select_dtypes(include=['category']).columns
for c in columns:
catValues1 = list(df1[c].cat.categories)
catValues2 = list(df2[c].cat.categories)
catValues = list(set(catValues1 + catValues2))
df1[c] = df1[c].cat.set_categories(catValues)
df2[c] = df2[c].cat.set_categories(catValues)
return df1.append(df2, ignore_index=True).reset_index(drop=True)
<小时/>
现在当我运行时:
print appendDFsWithCat(df1.iloc[:-1], df1)
我得到:
cat val
0 a 1
1 a 2
2 b 3
3 a 1
4 a 2
5 b 3
6 b 4
现在有警告。
我是一名优秀的程序员,十分优秀!