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

如何用Pandas GroupBy按最新行的Serial值更新组内所有行?

按ID分组替换Pandas DataFrame的Serial列

需求说明

给定包含id、location、serial、valid_from、valid_to列的Pandas DataFrame,需按id分组,将每组内所有行的serial列值替换为该组中valid_from日期最新的行的serial值。因数据中id数量庞大,需采用高效的GroupBy方案实现。

原始数据构建

import pandas as pd
import numpy as np

df = pd.DataFrame(
    data=[
        ['X', 'L1', 'S2', '2023-06-26', '2023-06-27'],
        ['X', 'L2', 'S2', '2023-06-27', '9999-01-01'],
        ['X', 'L2', 'S2', '2023-06-28', np.nan]
    ],
    columns=['id', 'location', 'serial', 'valid_from', 'valid_to']
)

实现步骤

  1. 转换日期列类型
    先将valid_from转换为datetime类型,确保能正确比较日期先后:

    df['valid_from'] = pd.to_datetime(df['valid_from'])
    
  2. 提取每组最新日期对应的Serial值
    通过sort_values和groupby组合,高效获取每个id组内valid_from最新的行的serial值:

    # 按日期升序排序后,每组最后一行即为日期最新的记录
    latest_serial = df.sort_values('valid_from').groupby('id')['serial'].last()
    
  3. 替换原DataFrame的Serial列
    用map方法将每组对应的最新serial值映射回原DataFrame:

    df['serial'] = df['id'].map(latest_serial)
    

效果验证

若修改测试数据,将第三行的serial改为S3:

df_test = pd.DataFrame(
    data=[
        ['X', 'L1', 'S2', '2023-06-26', '2023-06-27'],
        ['X', 'L2', 'S2', '2023-06-27', '9999-01-01'],
        ['X', 'L2', 'S3', '2023-06-28', np.nan]
    ],
    columns=['id', 'location', 'serial', 'valid_from', 'valid_to']
)
df_test['valid_from'] = pd.to_datetime(df_test['valid_from'])
latest_serial_test = df_test.sort_values('valid_from').groupby('id')['serial'].last()
df_test['serial'] = df_test['id'].map(latest_serial_test)
print(df_test)

输出结果:

id location serial valid_from   valid_to
0  X       L1     S3 2023-06-26 2023-06-27
1  X       L2     S3 2023-06-27 9999-01-01
2  X       L2     S3 2023-06-28        NaN

可见同一id下所有行的serial都被替换为该组最新日期对应的S3。

方案优势

该方案基于Pandas原生的GroupBy和map操作,避免了低效的循环遍历,能够高效处理包含大量id的数据集,保证运算性能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 14:52:47