如何基于现有Series与DataFrame实现Pandas查找生成新Series?
解决方法:从匹配的MultiIndex DataFrame中提取对应列的值
嘿,这个需求其实很好实现,核心就是利用pandas的索引对齐特性,或者专门的查找方法来匹配行和列。先给你把完整的代码和思路理清楚:
1. 先还原你的数据(方便复现)
首先我们先把你给出的Series S 和DataFrame df 用代码构造出来,确保环境一致:
import pandas as pd # 构造Series S index = pd.MultiIndex.from_tuples( [ ('andrew', 'alexander', 'baseline'), ('andrew', 'alexander', 'followup'), ('bruce', 'alexander', 'baseline'), ('bruce', 'alexander', 'followup'), ('fuzzy', 'dunlop', 'baseline'), ('fuzzy', 'dunlop', 'followup'), ], names=['first', 'last', 'visit'] ) S = pd.Series( ['abc', 'abc', 'abc', 'xyz', 'xyz', 'abc'], index=index, name='attr' ) # 构造DataFrame df df = pd.DataFrame( [[1,7], [2,8], [3,9], [4,10], [5,11], [6,12]], index=index, columns=['abc', 'xyz'] )
2. 生成目标Series S2的两种方法
方法一:使用df.lookup(简单直接)
lookup方法就是专门用来根据行索引和列标签的对应关系提取值的,刚好符合我们的场景:
- 行索引直接用
S的索引(和df的索引完全匹配) - 列标签用
S的每个值(也就是我们要取的列名)
代码如下:
# 生成S2 S2 = pd.Series(df.lookup(S.index, S.values), index=S.index, name='result')
运行后S2的结果就是:
first last visit andrew alexander baseline 1 followup 2 bruce alexander baseline 3 followup 10 fuzzy dunlop baseline 11 followup 6 Name: result, dtype: int64
方法二:用stack+索引匹配(更现代,避免deprecated警告)
注意:lookup在pandas的新版本中被标记为deprecated,如果想避免警告,可以用stack把列转成索引的一部分,然后通过组合索引来取值:
# 把df的列转成索引层级,得到一个4级索引的Series stacked_df = df.stack() # 构造一个包含原索引+S值的4级索引,用来匹配stacked_df lookup_index = pd.MultiIndex.from_tuples( [(*idx, val) for idx, val in zip(S.index, S.values)], names=['first', 'last', 'visit', 'attr'] ) # 提取对应值后,去掉多余的attr索引层级 S2 = stacked_df.loc[lookup_index].reset_index(level=3, drop=True)
这个方法得到的S2和方法一完全一致,而且更符合pandas的现代索引操作逻辑。
内容的提问来源于stack exchange,提问作者ajwood
相关产品推荐
相关产品推荐

