这是我的 2 美分,有一个非常简单的例子,为什么警告很重要。
所以假设我正在创建一个这样的df
x = pd.DataFrame(list(zip(range(4), range(4))), columns=['a', 'b'])
print(x)
a b
0 0 0
1 1 1
2 2 2
3 3 3
现在我想根据原始数据的一个子集创建一个新的数据框并对其进行修改,如下所示:
q = x.loc[:, 'a']
现在这是原版的一部分,无论我在上面做什么都会影响 x:
q += 2
print(x) # checking x again, wow! it changed!
a b
0 2 0
1 3 1
2 4 2
3 5 3
这就是警告告诉你的。您正在处理切片,因此您在切片上所做的一切都会反映在原始 DataFrame 上
现在使用.copy()
,它不会是原始的一部分,所以对 q 进行操作不会影响 x :
x = pd.DataFrame(list(zip(range(4), range(4))), columns=['a', 'b'])
print(x)
a b
0 0 0
1 1 1
2 2 2
3 3 3
q = x.loc[:, 'a'].copy()
q += 2
print(x) # oh, x did not change because q is a copy now
a b
0 0 0
1 1 1
2 2 2
3 3 3
顺便说一句,副本只是意味着q
它将成为内存中的一个新对象。切片在内存中共享相同的原始对象
imo,使用.copy()
非常安全。例如,df.loc[:, 'a']
返回一个切片但df.loc[df.index, 'a']
返回一个副本。Jeff 告诉我这是一个意外的行为,:
或者df.index
应该与 .loc[] 中的索引器具有相同的行为,但是.copy()
在两者上使用都会返回一个副本,最好是安全的。因此,.copy()
如果您不想影响原始数据框,请使用。
现在使用.copy()
返回 DataFrame 的深层副本,这是一种非常安全的方法,不会接到您正在谈论的电话。
但是使用df.is_copy = None
, 只是一个不复制任何东西的技巧,这是一个非常糟糕的主意,您仍将处理原始 DataFrame 的一部分
人们往往不知道的另一件事:
df[columns]
可能会返回视图。
df.loc[indexer, columns]
也可能会返回一个视图,但在实践中几乎总是不会。这里
强调五月