基于ID与上一行数据计算并填充DataFrame的Start Value
用Pandas实现分组递推填充Start Value
没问题,我来帮你搞定这个需求!我们需要按ID分组,对每组内的日期行进行递推计算:首日保留初始Start Value,之后每天的Start Value等于前一天的Start Value减去前一天的Payment。下面是具体实现步骤:
1. 构造标准DataFrame
首先把你提供的数据转换成Pandas可处理的格式(补充缺失的列值,非首日的Start Value设为NaN,Payment列补全):
import pandas as pd data = { 'ID': [111, 111, 111, 111, 111, 222, 222, 222, 222, 222, 222, 222], 'Date': ['1/1/2018', '1/2/2018', '1/3/2018', '1/4/2018', '1/5/2018', '4/1/2018', '4/2/2018', '4/3/2018', '4/4/2018', '4/5/2018', '4/6/2018', '4/7/2018'], 'Start Value': [1000, None, None, None, None, 2000, None, None, None, None, None, None], 'Payment': [0, 100, 500, 400, 0, 200, 100, 700, 0, 0, 1000, 0] } df = pd.DataFrame(data) # 转换日期格式并确保分组内按时间排序(关键!避免计算顺序错误) df['Date'] = pd.to_datetime(df['Date']) df = df.sort_values(['ID', 'Date']).reset_index(drop=True)
2. 核心计算逻辑
我们可以用两种方式实现:一种是直观的遍历递推,适合理解;另一种是向量化计算,适合大数据集。
方式一:遍历递推(逻辑清晰)
定义一个分组处理函数,对每个ID组逐行计算:
def fill_start_value(group): # 获取组内首日的初始Start Value initial_start = group['Start Value'].iloc[0] start_values = [initial_start] # 从第二行开始递推计算 for i in range(1, len(group)): prev_start = start_values[i-1] prev_payment = group['Payment'].iloc[i-1] current_start = prev_start - prev_payment start_values.append(current_start) group['Start Value'] = start_values return group # 应用到每个ID分组 df_filled = df.groupby('ID', group_keys=False).apply(fill_start_value)
方式二:向量化计算(高效快速)
利用cumsum实现累计求和,避免循环,速度更快:
def fill_start_value_vectorized(group): # 计算Payment的累计和,偏移1位(取前序Payment的累计),初始位置填充0 payment_cumsum = group['Payment'].cumsum().shift(1).fillna(0) # 初始值减去前序Payment的累计和 group['Start Value'] = group['Start Value'].iloc[0] - payment_cumsum return group df_filled = df.groupby('ID', group_keys=False).apply(fill_start_value_vectorized)
3. 查看结果
运行后打印df_filled,会得到填充完成的DataFrame:
ID Date Start Value Payment 0 111 2018-01-01 1000.0 0 1 111 2018-01-02 1000.0 100 2 111 2018-01-03 900.0 500 3 111 2018-01-04 400.0 400 4 111 2018-01-05 0.0 0 5 222 2018-04-01 2000.0 200 6 222 2018-04-02 1800.0 100 7 222 2018-04-03 1700.0 700 8 222 2018-04-04 1000.0 0 9 222 2018-04-05 1000.0 0 10 222 2018-04-06 1000.0 1000 11 222 2018-04-07 0.0 0
注意事项
- 一定要确保每个ID组内的行是按日期顺序排列的,否则递推计算会出错,所以我们提前做了排序处理。
- 如果你的原始数据已经是按ID和日期排序的,可以跳过
sort_values步骤,但建议保留以避免潜在问题。
内容的提问来源于stack exchange,提问作者qqqwww
相关产品推荐
相关产品推荐

