Python Pandas:按ID分组更新参数最新日期值(简单动态规则)
问题与解决方案
问题背景
现有一个按季度日期记录各ID对应参数的DataFrame,初始为随机打乱状态,需先按fab_date和id排序,数据构造代码如下:
import pandas as pd import numpy as np np.random.seed(1) dt_to_fun = pd.DataFrame({ 'fab_date': pd.to_datetime(["2022-01-01", "2022-07-01", "2023-01-01", "2023-07-01", "2022-01-01", "2022-07-01", "2023-01-01", "2023-07-01", "2022-01-01", "2022-07-01", "2023-01-01", "2023-07-01"]), 'id': ['n_01', 'n_01', 'n_01', 'n_01', 'n_02', 'n_02', 'n_02', 'n_02', 'n_03', 'n_03', 'n_03', 'n_03'], 'param_01': np.random.choice([10, 20, 30], size=12), 'param_02': np.random.choice([10, 30, 50], size=12) })
初始数据如下:
fab_date id param_01 param_02 0 2022-01-01 n_01 20 30 1 2022-07-01 n_01 10 50 2 2023-01-01 n_01 10 10 3 2023-07-01 n_01 20 50 4 2022-01-01 n_02 20 30 5 2022-07-01 n_02 10 50 6 2023-01-01 n_02 10 10 7 2023-07-01 n_02 20 10 8 2022-01-01 n_03 10 50 9 2022-07-01 n_03 20 10 10 2023-01-01 n_03 10 30 11 2023-07-01 n_03 30 50
需求:对每个ID,仅更新其最新日期行的所有param*列值,更新规则为:param(最新日期) = param(最新日期) + param(上一日期) - param(上上个日期)
例如ID n_03的param_02最新值为50,上一值为30,上上个值为10,更新后应为50+30-10=70。期望结果如下:
fab_date id param_01 param_02 0 2022-01-01 n_01 20 30 1 2022-07-01 n_01 10 50 2 2023-01-01 n_01 10 10 3 2023-07-01 n_01 20 10 4 2022-01-01 n_02 20 30 5 2022-07-01 n_02 10 50 6 2023-01-01 n_02 10 10 7 2023-07-01 n_02 20 -30 8 2022-01-01 n_03 10 50 9 2022-07-01 n_03 20 10 10 2023-01-01 n_03 10 30 11 2023-07-01 n_03 20 70
解决方案
可以通过以下步骤实现需求:
- 先按
id和fab_date排序,确保每个ID的日期是按顺序排列的:
dt_to_fun = dt_to_fun.sort_values(['id', 'fab_date']).reset_index(drop=True)
- 筛选出所有
param*列,方便后续批量处理:
param_cols = [col for col in dt_to_fun.columns if col.startswith('param_')]
- 按
id分组,计算每个参数的上一日期值(shift(1))和上上个日期值(shift(2)),然后计算更新增量:
# 计算每个param列的更新增量:shift(1) - shift(2) update_delta = dt_to_fun.groupby('id')[param_cols].shift(1) - dt_to_fun.groupby('id')[param_cols].shift(2)
- 仅对每个ID的最新行应用更新,通过标记每个组的最后一行来定位目标行:
# 标记每个ID的最新行(最后一行) is_last_row = dt_to_fun.groupby('id').tail(1).index # 对最新行的param列加上增量 dt_to_fun.loc[is_last_row, param_cols] += update_delta.loc[is_last_row, param_cols].values
完整代码
import pandas as pd import numpy as np np.random.seed(1) dt_to_fun = pd.DataFrame({ 'fab_date': pd.to_datetime(["2022-01-01", "2022-07-01", "2023-01-01", "2023-07-01", "2022-01-01", "2022-07-01", "2023-01-01", "2023-07-01", "2022-01-01", "2022-07-01", "2023-01-01", "2023-07-01"]), 'id': ['n_01', 'n_01', 'n_01', 'n_01', 'n_02', 'n_02', 'n_02', 'n_02', 'n_03', 'n_03', 'n_03', 'n_03'], 'param_01': np.random.choice([10, 20, 30], size=12), 'param_02': np.random.choice([10, 30, 50], size=12) }) # 排序 dt_to_fun = dt_to_fun.sort_values(['id', 'fab_date']).reset_index(drop=True) # 筛选param列 param_cols = [col for col in dt_to_fun.columns if col.startswith('param_')] # 计算更新增量 update_delta = dt_to_fun.groupby('id')[param_cols].shift(1) - dt_to_fun.groupby('id')[param_cols].shift(2) # 更新最新行 is_last_row = dt_to_fun.groupby('id').tail(1).index dt_to_fun.loc[is_last_row, param_cols] += update_delta.loc[is_last_row, param_cols].values print(dt_to_fun)
内容的提问来源于stack exchange,提问作者Howdyouride
相关产品推荐
相关产品推荐

