Pandas使用iloc复制未按预期工作

1 投票
1 回答
5778 浏览
提问于 2025-04-18 11:06

我对pandas还比较陌生,所以可能还没完全理解它。我一直在尝试复制一个数据框(dataframe),并且需要根据外部提供的映射来重新排列行(这样做有个很好的但不相关的理由,所以我把df2设为nan)。当我尝试用.iloc一次性完成这个操作时,排列顺序被忽略了,但如果我逐行循环处理,就能按我预期的那样工作。有没有人能告诉我在这个简单示例中我哪里出错了?(另外,如果有更高效或更优雅的方法也欢迎分享)。

import pandas as pd
import numpy as np

df1 = pd.DataFrame([[100,200,300,400]]).T
df1.columns = ['A']

df2 = df1.copy()
df2[:] = np.nan

assign = np.array([[0,0],[1,1],[3,2],[2,3]])

print df1

# This does not work:
# df2.iloc[assign[:,1]] = df1.iloc[assign[:,0]]
# Output:
#      A
# 0  100
# 1  200
# 2  300
# 3  400
#
#      A
# 0  100
# 1  200
# 2  300
# 3  400

# This does:
for x in assign:
  df2.iloc[x[1]] = df1.iloc[x[0]]
# Output:
#      A
# 0  100
# 1  200
# 2  300
# 3  400
#
#      A
# 0  100
# 1  200
# 2  400
# 3  300

print df2

1 个回答

2

我们需要一个 pandas 的开发者来解释为什么它是这样工作的,不过我知道下面这个解决方案可以帮你解决问题(适用于 pandas 0.13.1):

In [179]:
df2.iloc[assign[:,1]] = df1.iloc[assign[:,0]].values
print df2

out[179]:
     A
0  100
1  200
2  400
3  300

[4 rows x 1 columns] 

正如 @Jeff 指出的,在 df2.iloc[assign[:,1]] = df1.iloc[assign[:,0]] 这行代码中,你是把一个 Series 赋值给另一个 Series,这样两个索引会对应上。但是在 df2.iloc[assign[:,1]] = df1.iloc[assign[:,0]].values 这行代码中,你是把一个 array 赋值给一个 Series,这样就没有索引可以对应了。

另外,考虑下面这个例子,可以帮助你理解索引匹配的行为。

In [208]:
#this will work and there will be missing values
df1['B']=pd.Series({0:'a', 3:'b', 2:'c'})
print df1
     A    B
0  100    a
1  200  NaN
2  300    c
3  400    b

[4 rows x 2 columns]
In [209]:
#this won't work
df1['B']=['a', 'b', 'c'] #one element less than df1
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)

撰写回答