如何用.loc从多级索引DataFrame高效填充目标DataFrame的val列?
高效实现用多级索引DataFrame填充普通DataFrame列的方法
首先,咱们先聊聊你原来代码里的几个小问题,再给出更简洁高效的解决方案:
原代码的问题点
loc语法错误:你写的df2.loc([row['key1'],row['key2'])是错误的,Pandas的loc是属性访问器,应该用方括号df2.loc[(row['key1'], row['key2'])],而且还需要指定提取b列,否则会返回整个行的Series。- 循环效率低下:
iterrows()遍历DataFrame属于逐行操作,在数据量大的时候速度会很慢,Pandas本身是为矢量化操作设计的,应该尽量避免这种循环。 - 定位行的方式冗余:循环里用
(df1.key1 == row['key1']) & (df1.key2 == row['key2'])来定位行完全没必要,直接用循环的index就能精准定位。
推荐解决方案
方法1:利用索引映射(最简洁高效)
把df1的key1和key2转成和df2一致的多级索引,然后用map结合get方法匹配值,未匹配到的自动返回空值:
# 将df1的key1、key2设为多级索引,匹配df2的b列后赋值给val df1['val'] = df1.set_index(['key1', 'key2']).index.map(df2['b'].get)
这个方法完全是矢量化操作,速度比循环快几个数量级,而且代码非常简洁。
方法2:用merge合并(直观易懂)
如果觉得索引映射有点抽象,可以用merge来做左连接,把df2的多级索引转成普通列后再匹配:
# 把df2的多级索引转为普通列,然后和df1左连接 df_temp = df2.reset_index() df_merged = df1.merge(df_temp, left_on=['key1', 'key2'], right_on=['c', 'a'], how='left') # 把匹配到的b列值赋值给df1的val df1['val'] = df_merged['b']
这个方法逻辑清晰,适合刚接触Pandas的朋友理解,结果和方法1完全一致。
修正后的循环版本(不推荐,但可以参考)
如果你一定要用循环,修正语法和定位方式后的代码如下:
for index, row in df1.iterrows(): try: # 正确使用loc访问多级索引,并指定b列 data = df2.loc[(row['key1'], row['key2']), 'b'] # 直接用循环的index定位行,避免全表扫描 df1.loc[index, 'val'] = data except KeyError: # 只捕获索引不存在的错误,避免隐藏其他异常 pass
但还是强烈推荐前面的矢量化方法,尤其是数据量较大时。
执行完推荐的方法后,你会得到期望的结果:
| key1 | key2 | val |
|---|---|---|
| 1 | 100 | a |
| 2 | 500 | NaN |
| 4 | 400 | e |
内容的提问来源于stack exchange,提问作者Shubham R
相关产品推荐
相关产品推荐

