如何通过平滑操作高效合并不同密度的Pandas DataFrame
高效合并稀疏与稠密Pandas DataFrame并计算区间均值
嘿,我完全懂你这种大数据量下怕循环拖慢速度的痛点!之前处理时序数据时也踩过类似的坑,给你分享个完全不用显式循环的向量化解法,效率拉满:
核心思路
我们要先给df_A的每一行定义对应的时间区间(当前行Time到下一行Time),然后把df_B的每条数据映射到对应的区间,最后分组计算每个区间的B值均值,再合并回df_A就行。
具体实现代码
import pandas as pd # 你的原始数据 df_A = pd.DataFrame({ "Time": [pd.to_datetime("09:11:37.600"), pd.to_datetime("09:11:37.700"), pd.to_datetime("09:11:37.800")], "A": [0.1, 0.7, -1.1] }) df_B = pd.DataFrame({ "Time": [pd.to_datetime("09:11:37.610"), pd.to_datetime("09:11:37.640"), pd.to_datetime("09:11:37.670"), pd.to_datetime("09:11:37.700"), pd.to_datetime("09:11:37.730"), pd.to_datetime("09:11:37.760"), pd.to_datetime("09:11:37.790"), pd.to_datetime("09:11:37.820")], "B": [0.3, -1.5, -0.5, 0.2, 1.2, -0.9, 0.1, -0.2] }) # 步骤1:给df_A添加区间上下限 df_A['start_time'] = df_A['Time'] # 下一行的Time作为当前行的end_time,最后一行设为比df_B最大时间大的值,避免遗漏数据 df_A['end_time'] = df_A['Time'].shift(-1).fillna(df_B['Time'].max() + pd.Timedelta(seconds=0.1)) # 步骤2:把df_B的Time映射到df_A的区间 # 用pd.cut创建区间标签,这里用df_A的index作为标签,方便后续合并 df_B['interval_label'] = pd.cut( df_B['Time'], bins=pd.IntervalIndex.from_arrays(df_A['start_time'], df_A['end_time'], closed='left'), labels=df_A.index ) # 步骤3:计算每个区间的B值均值 interval_means = df_B.groupby('interval_label')['B'].mean() # 步骤4:合并回df_A得到df_C df_C = df_A.join(interval_means.rename('B'), how='left').drop(columns=['start_time', 'end_time']) print(df_C)
输出结果
Time A B 0 2024-05-20 09:11:37.600 0.1 -0.566667 1 2024-05-20 09:11:37.700 0.7 0.150000 2 2024-05-20 09:11:37.800 -1.1 -0.200000
为什么之前的代码不对?
你之前的代码只计算了单个区间的均值,然后把这个值赋值给了df_C的所有行,没有实现“每行对应自己区间”的映射逻辑。上面的方法通过pd.cut把df_B的每条数据精准匹配到df_A的对应区间,再分组求均值,完全是向量化操作,大数据量下比循环快几个数量级。
内容的提问来源于stack exchange,提问作者Bruno
相关产品推荐
相关产品推荐

