You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas中合并多时间维度DataFrame的更优实现方式探讨

问题解答

当前代码是否符合Pandas最佳实践?

不符合。当前代码存在大量重复的merge、drop、rename操作,违反了DRY(Don't Repeat Yourself)原则,不仅代码冗余,后期维护成本高(比如新增偏移量时需要重复编写几乎相同的代码),而且多次使用inplace=True修改原DataFrame,虽然功能正常,但并非最优雅的写法。

更优实现方式

方式一:循环批量处理(适合少量偏移量)

利用循环遍历需要的偏移值,结合merge的suffixes参数自动命名列,避免重复的drop和rename操作:

import pandas as pd

reference_df = pd.DataFrame({'id' : [ 1,  1,  1,  1, 2,  2,  2,  2,
                                     3, 3, 3, 3, 4, 4, 4, 4],
                   'time' : [1, 2, 3, 4, 1, 2, 3, 4,
                             1, 2, 3, 4, 1, 2, 3, 4],
                   'value_initial'  : [1, 2, 2, 3,
                                2, 3, 3, 3,
                                1, 1, 1, 1,
                                2, 2, 2, 2],
                   'value_final'  : [5, 5, 5, 5,
                                4, 4, 4, 4,
                                3, 3, 3, 3,
                                4, 4, 4, 4]})


df = pd.DataFrame({'id' : [5,6],
                   'time': [3, 4],
                   'value_present': [11, 12]})

# 定义需要的偏移量
offsets = [1, 2, 3]
df_result = df.copy()

for offset in offsets:
    # 直接merge,通过left_on动态计算past_id,无需提前创建列
    df_result = df_result.merge(
        reference_df[['id', 'time', 'value_initial', 'value_final']],
        left_on=[df_result['id'] - offset, 'time'],
        right_on=['id', 'time'],
        how='left',
        suffixes=('', f'_{offset}')
    )
    # 删除merge后冗余的id和time列(来自reference_df)
    df_result.drop(columns=['id', 'time'], inplace=True)

# 恢复原始的id和time列名
df_result.rename(columns={'id_3': 'id', 'time_3': 'time'}, inplace=True)

方式二:长格式转宽格式(适合大量偏移量,扩展性更强)

通过将原始DataFrame转换为长格式,一次性完成合并后再转回宽格式,彻底避免重复操作:

import pandas as pd

reference_df = pd.DataFrame({'id' : [ 1,  1,  1,  1, 2,  2,  2,  2,
                                     3, 3, 3, 3, 4, 4, 4, 4],
                   'time' : [1, 2, 3, 4, 1, 2, 3, 4,
                             1, 2, 3, 4, 1, 2, 3, 4],
                   'value_initial'  : [1, 2, 2, 3,
                                2, 3, 3, 3,
                                1, 1, 1, 1,
                                2, 2, 2, 2],
                   'value_final'  : [5, 5, 5, 5,
                                4, 4, 4, 4,
                                3, 3, 3, 3,
                                4, 4, 4, 4]})


df = pd.DataFrame({'id' : [5,6],
                   'time': [3, 4],
                   'value_present': [11, 12]})

# 定义需要的偏移量
offsets = [1, 2, 3]

# 步骤1:将df转换为长格式,生成每个id对应的所有past_id
df_long = df.assign(offset=offsets).explode('offset')
df_long['past_id'] = df_long['id'] - df_long['offset']

# 步骤2:与reference_df合并
merged = df_long.merge(
    reference_df,
    left_on=['past_id', 'time'],
    right_on=['id', 'time'],
    how='left'
)

# 步骤3:转回宽格式并调整列名
df_result = merged.pivot(
    index=['id', 'time', 'value_present'],
    columns='offset',
    values=['value_initial', 'value_final']
).reset_index()

# 重命名列,比如value_initial_1、value_final_2
df_result.columns = [f'{col[0]}_{col[1]}' if col[1] != '' else col[0] for col in df_result.columns]

这两种方式都比原代码更简洁、易维护,且符合Pandas的最佳实践:

  • 减少重复代码,提升扩展性
  • 避免不必要的中间列创建
  • 更清晰的数据流逻辑

内容的提问来源于stack exchange,提问作者user13744439

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 14:00:34