Pandas 为过滤后的数据帧/系列分配值。为什么不一致?

use*_*363 3 python pandas

TL;DR:使用.loc[:, 'foo']而不是.foo


pandas 什么时候给视图赋值,什么时候给副本赋值?

AFAIK,pandas 要么返回视图,要么返回副本,具体取决于您使用的方法。

如果为视图分配值,则可以更改原始数据框,但如果为副本分配值,则无法更改原始数据框。

然而,下面的行为让我感到困惑。为什么为视图分配值适用于数据框而不适用于系列?

dd = pd.DataFrame([
    {'a': 1, 'b': 2},
    {'a': 2, 'b': 4},
    {'a': 4, 'b': 3},
])

dd[dd.a == 1] = pd.DataFrame([{'a': 100, 'b': 200}]) # Assigning value works. 

dd
>>  a   b
0   100 200
1   2   4
2   4   3
Run Code Online (Sandbox Code Playgroud)

正如预期的那样,第一行的值已更改。

但是,如下所示,为系列分配值不起作用,即使设置相同(除了我称为系列之外)。

dd = pd.DataFrame([
    {'a': 1, 'b': 2},
    {'a': 2, 'b': 4},
    {'a': 4, 'b': 3},
])

dd[dd.a == 1].a = 1000 # Assigning value doesn't work.  

dd
>>  a   b
0   1   2
1   2   4
2   4   3
Run Code Online (Sandbox Code Playgroud)

不过我在 pandas 0.19.1 上。(因为我使用的是Python 2.7)

Aks*_*gal 6

太长了;

我想你自己已经回答了你的问题。为视图分配值的行为方式与您期望的方式相同,而为副本分配值不会修改原始数据框。

在本质上;

  • dd[dd.a == 1].a是数据帧切片中值的副本
  • dd.a[dd.a == 1]是同一数据帧的另一个切片 (df.a) 的切片(按条件)的视图。

以下是数据帧的条件切片dd,因此它是数据帧的视图。同样,带有 的loc,这是推荐的方式。

dd[dd.a == 1] #Slice of a dataframe based on condition returned as a view

dd.loc[dd.a == 1] #Slice of a dataframe based on condition returned as a view

Run Code Online (Sandbox Code Playgroud)

当您从此切片中提取特定列时,您最终会得到一个副本 -

dd[dd.a == 1].a = 100 
#This syntax basically says - 
#From the view of a slice of dd, give me values of 'a' and set that to 100"
#The assignment here is that to a copy and not to a view
Run Code Online (Sandbox Code Playgroud)
   a  b
0  1  2
1  2  4
2  4  3
Run Code Online (Sandbox Code Playgroud)

因此分配不会对原始数据帧产生影响。

如果您想为特定列进行分配,那么您需要这样做 -

dd.a[dd.a == 1] = 100
#This syntax basically says - 
#"From the slice, dd.a give me aother slice based on condition and set that slice to 100"
#The assignment happens a sliced view of the dataframe itself
Run Code Online (Sandbox Code Playgroud)
     a  b
0  100  2
1    2  4
2    4  3
Run Code Online (Sandbox Code Playgroud)

希望这能回答你的问题。

  • 完美解释!我对 Pandas 如何处理数据帧的复制/视图有一个模糊的了解。 (2认同)