如何在Pandas中将多年合计数据按规则分摊到各对应年度?
Pandas数据分摊转换实现方案
首先从示例可推导分摊规则如下:
- 单个项目的年度基准分摊额 = 项目总金额 ÷ 项目时长
- 项目覆盖的年份范围为:从开始年起,到「开始年 + 时长向下取整」的年份为止
- 覆盖范围内前N个完整年度(N=时长向下取整)每年分摊全额基准额,若时长存在小数部分,最后一年分摊 小数比例 × 基准额
- 同个项目同一年度存在多个分摊记录时,金额合并求和
- 最终金额格式为带$符号的千分位格式
完整实现代码
import pandas as pd import numpy as np # 1. 构造原始数据集 raw_data = { "Program": ["a", "a", "b"], "Start year": [2021, 2022, 2020], "Duration": [2, 3, 2.5], "Total amount": ["$30000", "$3000", "$15000"] } df = pd.DataFrame(raw_data) # 2. 预处理数据:转换金额为数值,计算年度基准分摊额 df["total_num"] = df["Total amount"].str.replace("$", "").astype(int) df["annual_base"] = df["total_num"] / df["Duration"] # 3. 按行展开生成各年度分摊记录 split_rows = [] for _, row in df.iterrows(): prog = row["Program"] start_y = row["Start year"] dur = row["Duration"] base = row["annual_base"] full_years = int(np.floor(dur)) remain = dur - full_years # 处理完整年份的分摊 for i in range(full_years): split_rows.append({ "Program": prog, "Year": start_y + i, "Annual amount": base }) # 处理剩余不足一年的部分 if remain > 0: split_rows.append({ "Program": prog, "Year": start_y + full_years, "Annual amount": base * remain }) # 4. 合并记录,按项目和年份分组求和 res_df = pd.DataFrame(split_rows).groupby(["Program", "Year"], as_index=False)["Annual amount"].sum() # 5. 格式化金额为要求的字符串格式 res_df["Annual amount"] = res_df["Annual amount"].apply(lambda x: f"${x:,.0f}")
输出结果
运行上述代码后得到的结果和目标格式完全一致:
| Program | Year | Annual amount |
|---|---|---|
| a | 2021 | $15,000 |
| a | 2022 | $16,000 |
| a | 2023 | $1,000 |
| a | 2024 | $1,000 |
| b | 2020 | $6,000 |
| b | 2021 | $6,000 |
| b | 2022 | $3,000 |
内容的提问来源于stack exchange,提问作者DaramG K
相关产品推荐
相关产品推荐

