我有一个数据框:
名字 | 年龄 | |
---|---|---|
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? 这是某种错误还是有意的行为?我无法弄清楚这种行为的原因。
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
。
loc
分配,所有索引轴都是对齐的,包括列:由于
age
和 name
不匹配,因此没有要分配的数据,因此是 NaN。您可以通过重命名列来使其工作:
df.loc[:, ["name"]] = df.loc[:, ["age"]].rename(columns={"age": "name"})
或者通过访问 numpy 数组:
df.loc[:, ["name"]] = df.loc[:, ["age"]].values
这是一些代码:
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