如何快速从另一个时序DataFrame映射时序DataFrame的值
问题描述
我有两个时序DataFrame:
from pandas import Timestamp import pandas as pd df1 = pd.DataFrame(index=[Timestamp('2023-12-22 00:01:00'), Timestamp('2023-12-22 00:02:00')], columns=['Peter', 'Adam'], data=[['A', 'C'], ['C', 'D']]) df2 = pd.DataFrame(index=[Timestamp('2023-12-22 00:01:00'), Timestamp('2023-12-22 00:01:00'), Timestamp('2023-12-22 00:01:00'), Timestamp('2023-12-22 00:01:00'), Timestamp('2023-12-22 00:02:00'), Timestamp('2023-12-22 00:02:00'), Timestamp('2023-12-22 00:02:00'), Timestamp('2023-12-22 00:02:00')], columns=['Level', 'Score'], data=[['A', 1], ['B', 2], ['C', 3], ['D', 4], ['A', 5], ['B', 6], ['C', 7], ['D', 8]])
df1内容:
Peter Adam 2023-12-22 00:01:00 A C 2023-12-22 00:02:00 C D
df2内容:
Level Score 2023-12-22 00:01:00 A 1 2023-12-22 00:01:00 B 2 2023-12-22 00:01:00 C 3 2023-12-22 00:01:00 D 4 2023-12-22 00:02:00 A 5 2023-12-22 00:02:00 B 6 2023-12-22 00:02:00 C 7 2023-12-22 00:02:00 D 8
我希望得到如下结果:
Peter Adam 2023-12-22 00:01:00 1 3 2023-12-22 00:02:00 7 8
虽然可以通过循环、按列遍历df1并使用apply等方法实现,但我认为存在更高效的转换方式,请问有什么解决方案?
解决方案
方法1:构建多级索引映射批量替换
先将df2转换为以时间索引+Level为键的映射关系,再直接匹配df1的元素:
# 构建(时间, Level)到Score的映射 score_map = df2.set_index([df2.index, 'Level'])['Score'] # 按行索引+元素值匹配映射 result = df1.apply(lambda col: col.combine(col.index, lambda x, idx: score_map.loc[(idx, x)]))
方法2:转宽表后对齐匹配
把df2从长表转为宽表,让Level作为列,直接和df1的结构对齐取值:
# 将df2转为宽表,时间为行索引,Level为列 df2_wide = df2.pivot(index=df2.index, columns='Level', values='Score') # 按df1的列和索引提取对应值 result = pd.DataFrame({col: df2_wide.loc[df1.index, df1[col]].values for col in df1.columns}, index=df1.index)
方法3:向量化lookup(性能最优)
利用pandas的lookup方法实现一次性批量提取,是效率最高的方案:
# 先将df2转为宽表 df2_wide = df2.pivot(index=df2.index, columns='Level', values='Score') # 批量提取对应时间+Level的Score值 result_values = df2_wide.lookup(df1.index, df1.values.ravel()).reshape(df1.shape) result = pd.DataFrame(result_values, index=df1.index, columns=df1.columns)
以上三种方法均比循环或逐元素apply高效,其中方法3的向量化操作适合处理大规模数据集。
内容的提问来源于stack exchange,提问作者Jackson Tale
相关产品推荐
相关产品推荐

