为什么使用两组括号进行 .loc 赋值会导致 pandas.DataFrame 中的 NaN ?

问题描述 投票:0回答:3

我有一个数据框:

名字 年龄
0 保罗 25
1 约翰 27
2 比尔 23

我知道如果我输入:

df[['name']] = df[['age']]

我会得到以下信息:

名字 年龄
0 25 25
1 27 27
2 23 23

但我期望命令得到相同的结果:

df.loc[:, ['name']] = df.loc[:, ['age']]

但是,我得到了这个:

名字 年龄
0 NaN 25
1 NaN 27
2 NaN 23

出于某种原因,如果我省略列名称周围的方括号

[]
,我将得到我所期望的结果。这就是命令:

df.loc[:, 'name'] = df.loc[:, 'age']

给出了正确的结果:

名字 年龄
0 25 25
1 27 27
2 23 23

为什么两对带有

.loc
的括号会导致 NaN? 这是某种错误还是有意的行为?我无法弄清楚这种行为的原因。

python pandas dataframe nan series
3个回答
12
投票

来自文档
Pandas Data Alignment
(强调我的):

pandas 在从 .loc 和 .iloc 设置 Series 和 DataFrame 时对齐所有 AXES

您可以在

Basics
标题下找到标有“警告”的摘录。 他们举了一个例子来解释。

In [9]: df[['A', 'B']]
Out[9]: 
                   A         B
2000-01-01 -0.282863  0.469112
2000-01-02 -0.173215  1.212112
2000-01-03 -2.104569 -0.861849
2000-01-04 -0.706771  0.721555
2000-01-05  0.567020 -0.424972
2000-01-06  0.113648 -0.673690
2000-01-07  0.577046  0.404705
2000-01-08 -1.157892 -0.370647

In [10]: df.loc[:, ['B', 'A']] = df[['A', 'B']]

In [11]: df[['A', 'B']]
Out[11]: 
                   A         B
2000-01-01 -0.282863  0.469112
2000-01-02 -0.173215  1.212112
2000-01-03 -2.104569 -0.861849
2000-01-04 -0.706771  0.721555
2000-01-05  0.567020 -0.424972
2000-01-06  0.113648 -0.673690
2000-01-07  0.577046  0.404705
2000-01-08 -1.157892 -0.370647

来自文档(强调我的)

这不会修改 df,因为列 对齐是在赋值之前。

明确避免自动对齐

当您需要在没有索引的情况下执行某些操作(例如禁用自动对齐)时,访问数组会很有用。

当 LHS 和 RHS 是数据帧时,对齐就会发挥作用。为了避免对齐,请尝试使用。

df.loc[:, ['B', 'A']] = df[['A', 'B']].to_numpy()


您手头有两个箱子,

  • .loc
     使用 
    pd.DataFrame
     进行分配。
  • .loc
     在编辑中使用 
    pd.Series
     进行分配。

.loc
 
pd.DataFrame
 中的作业

pd.DataFrame

 中有 2 个轴 
index
columns
。所以,当你这样做时

df.loc[:, ['name']] = df.loc[:, ['age']]

LHS 的列

A

 与 RHS 列 
B
 不对齐,因此分配后会出现所有 
NaN

  • 数据对齐和算术

来自文档

DataAlignment

(强调我的)

DataFrame 对象之间的数据自动对齐

在列和索引(行标签)上对齐。同样,生成的对象将具有列和行标签的并集。

即使不是全部,你也可以在大多数熊猫的操作中发现这种行为。例如,加法、减法、乘法等。不匹配的索引和列用

NaN

 填充。

数据对齐和算术示例

df = pd.DataFrame(np.random.randn(10, 4), columns=["A", "B", "C", "D"]) df2 = pd.DataFrame(np.random.randn(7, 3), columns=["A", "B", "C"]) df + df2 A B C D 0 0.045691 -0.014138 1.380871 NaN 1 -0.955398 -1.501007 0.037181 NaN 2 -0.662690 1.534833 -0.859691 NaN 3 -2.452949 1.237274 -0.133712 NaN 4 1.414490 1.951676 -2.320422 NaN 5 -0.494922 -1.649727 -1.084601 NaN 6 -1.047551 -0.748572 -0.805479 NaN 7 NaN NaN NaN NaN 8 NaN NaN NaN NaN 9 NaN NaN NaN NaN

回复您的

评论

但是为什么列索引需要匹配呢?我明白为什么要匹配行索引,但为什么要匹配列索引呢?

让我们看一下上面的例子,如果列没有对齐,你将如何添加两个DataFrame?将它们在列和索引上对齐是有意义的。


.loc
 
pd.Series
 中的作业

pd.Series

 只有 
一个 轴,即 index
。这就是你这样做时它起作用的原因

df.loc[:, 'name'] = df.loc[:, 'age']

由于

pd.Series

 只有一个轴,pandas 尝试对齐 
index
 并且成功了。当然,如果 
index
 未对齐,则会导致 
NaN
 值。

来自文档Series Alignment
(强调我的)

未对齐系列之间

操作的结果将具有所涉及索引的并集。如果在一个系列或另一个系列中未找到标签,则结果将被标记为缺失NaN


3
投票
loc

分配,所有索引轴都是对齐的,包括列:由于

age
name
不匹配,因此没有要分配的数据,因此是 NaN。
您可以通过重命名列来使其工作:

df.loc[:, ["name"]] = df.loc[:, ["age"]].rename(columns={"age": "name"})

或者通过访问 numpy 数组:

df.loc[:, ["name"]] = df.loc[:, ["age"]].values



1
投票

这是一些代码:

import pandas as pd df = pd.DataFrame({'name':['Paul','John','Bill'], 'age':[25,27,23]}) print('Inital Dataframe:\n',df) df[['name']] = df[['age']] print("\ndf[['name']] = df[['age']]\n",df) print("df.loc[:, ['age']]:", type(df.loc[:, ['age']])) print("df.loc[:, ['name']]:", type(df.loc[:, ['name']])) df.loc[:, ['name']] = df.loc[:, ['age']] print("\ndf.loc[:, ['name']] = df.loc[:, ['age']]\n",df) print('=======================') df = pd.DataFrame({'name':['Paul','John','Bill'], 'age':[25,27,23]}) print('Inital Dataframe:\n',df) print("type(df.loc[:, 'age']):", type(df.loc[:, 'age'])) print("type(df.loc[:, 'name']):", type(df.loc[:, 'name'])) df.loc[:, 'name'] = df.loc[:, 'age'] print("\ndf.loc[:, 'name'] = df.loc[:, 'age']\n",df)

输出:

Inital Dataframe: name age 0 Paul 25 1 John 27 2 Bill 23 df[['name']] = df[['age']] name age 0 25 25 1 27 27 2 23 23 df.loc[:, ['age']]: <class 'pandas.core.frame.DataFrame'> df.loc[:, ['name']]: <class 'pandas.core.frame.DataFrame'> df.loc[:, ['name']] = df.loc[:, ['age']] name age 0 NaN 25.0 1 NaN 27.0 2 NaN 23.0 ======================= Inital Dataframe: name age 0 Paul 25 1 John 27 2 Bill 23 type(df.loc[:, 'age']): <class 'pandas.core.series.Series'> type(df.loc[:, 'name']): <class 'pandas.core.series.Series'> df.loc[:, 'name'] = df.loc[:, 'age'] name age 0 25 25 1 27 27 2 23 23

但是,这是另一个奇怪的行为:将双括号分配给不同的变量,例如 
df1

df2
,然后
df1 = df2
起作用! 这是更多代码:
df = pd.DataFrame({'name':['Paul','John','Bill'], 'age':[25,27,23]})
print('Inital Dataframe:\n',df)

df1 = df.loc[:, ['name']]
df2 = df.loc[:, ['age']]
print("\ndf1 = df.loc[:, ['name']]\n",df1)
print("\ndf2 = df.loc[:, ['age']]\n",df2)

df1=df2
print("\ndf1=df2\ndf1:\n",df1)

输出:

Inital Dataframe: name age 0 Paul 25 1 John 27 2 Bill 23 df1 = df.loc[:, ['name']] name 0 Paul 1 John 2 Bill df2 = df.loc[:, ['age']] age 0 25 1 27 2 23 df1=df2 df1: age 0 25 1 27 2 23

© www.soinside.com 2019 - 2024. All rights reserved.