在下面的代码中,我将DataFrame的点的X值分组到 bins 中。现在我想将一个组ID分配给Y列,但是pandas继续向我发出类型为SettingWithCopyWarning
的警告。我做错了什么?
import numpy as np
import pandas as pd
d = np.random.random((10, 2))
d[:, 1] = 0
m = pd.DataFrame(d, columns=("x", "gid"))
dx = 0.2
grp = m.groupby(lambda i: int(m["x"][i] / dx))
gid = 1
for name, group in grp:
group["gid"][:] = gid # This line crashes!
gid += 1
print(m)
这是警告:
/usr/lib/python3.4/site-packages/pandas/core/series.py:677: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame
See the the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
self._set_with(key, value)
sys:1: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame
See the the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
答案 0 :(得分:1)
这里有两个问题。首先,您获得了SettingWithCopyWarning
,因为
group["gid"][:] = gid
使用“链式索引”。问题是,有时group[...]
可能会返回副本而不是group
的视图,因此进一步索引和修改副本,例如group[...][...] = gid
may be useless since it only modifies the copy而非group
。 SettingWithCopyWarning
是警告,已在分配中检测到链式索引。它并不一定意味着出了什么问题。在您的情况下,group["gid"]
会返回group
的视图,因此您的链式索引会成功修改group
本身。
尽管如此,建议的做法是始终在执行赋值时避免链式索引,因为并不总是很容易预测链式索引是否会返回视图或副本。
通常,您可以使用.loc
或iloc
来避免链式索引:
group.loc[:, "gid"] = gid
第二个问题是,即使我们避免使用链式索引,修改group
也不会修改m
。
使用for-loop
时:
for name, group in grp:
Python创建局部变量name
和group
,并将这些变量绑定到grp
中的项目。但是这些项目本身就是m
部分的副本,而不是视图。因此,修改这些副本不会影响m
。
您可以使用pd.Categorical
:
import numpy as np
import pandas as pd
np.random.seed(2015)
d = np.random.random((10, 2))
d[:, 1] = 0
m = pd.DataFrame(d, columns=("x", "gid"))
dx = 0.2
m['gid'] = pd.Categorical((m['x'] / dx).astype(int)).codes + 1
print(m)
产量
x gid
0 0.737595 3
1 0.884189 4
2 0.944676 4
3 0.063603 1
4 0.332454 2
5 0.003218 1
6 0.071058 1
7 0.289020 2
8 0.268896 2
9 0.258775 2