基于现有列值计算新列:按合同期限拆分金额至对应年份列
解决方案:Pandas按合同期限拆分金额到对应年份列
嘿,这是个很实用的合同金额拆分需求,我来给你分享两个用Pandas实现的方法,完全能达到你想要的效果!
首先先确认你的原始数据:
import pandas as pd df = pd.DataFrame( { "customer": ['c1', 'c2', 'c3', 'c4', 'c5'], "contract_year": [2018, 2020, 2019, 2018, 2019], "amount": [3000, 1000, 3000, 6000, 6000], "term": [3, 1, 2, 3, 3] } )
方法一:用explode + pivot拆分(直观易懂)
这个方法的思路是先给每个客户生成对应的支付年份列表,再把列表展开成单行记录,最后转置成列:
- 先计算每年要拆分的金额
- 生成每个客户的支付年份范围
- 展开年份列表,将每个年份拆成单独行
- 把年份转成列,合并回原始数据
代码实现:
# 计算每年的拆分金额 df['annual_amount'] = df['amount'] / df['term'] # 为每个客户生成支付年份的列表(从合同开始年到开始年+期限年,左闭右开) df['years'] = df.apply(lambda row: list(range(row['contract_year'], row['contract_year'] + row['term'])), axis=1) # 将年份列表展开,每一行对应一个年份和对应的年金额 exploded_df = df.explode('years') # 把年份转成列,提取每个索引对应的年金额,空值填充0并转成整数 pivoted_years = exploded_df.pivot(index=df.index, columns='years', values='annual_amount').fillna(0).astype(int) # 合并原始数据和年份列,去掉列名的层级 result = pd.concat([df.drop(['annual_amount', 'years'], axis=1), pivoted_years], axis=1) result.columns.name = None print(result)
运行后就能得到你想要的输出:
customer contract_year amount term 2018 2019 2020 2021 0 c1 2018 3000 3 1000 1000 1000 0 1 c2 2020 1000 1 0 0 1000 0 2 c3 2019 3000 2 0 1500 1500 0 3 c4 2018 6000 3 2000 2000 2000 0 4 c5 2019 6000 3 0 2000 2000 2000
方法二:直接生成年份列(适合固定年份范围)
如果需要明确指定要包含的年份范围,可以用这个方法,直接给每行生成对应年份的金额:
# 确定所有需要覆盖的年份范围 min_year = df['contract_year'].min() max_year = df['contract_year'].max() + df['term'].max() all_years = range(min_year, max_year) # 定义函数,为每行生成各年份的金额 def get_yearly_amounts(row): start_year = row['contract_year'] end_year = start_year + row['term'] annual_amount = row['amount'] / row['term'] # 为每个年份分配金额,不在期限内的为0 return pd.Series({year: annual_amount if start_year <= year < end_year else 0 for year in all_years}) # 应用函数生成年份列,转成整数后合并到原始数据 yearly_amounts = df.apply(get_yearly_amounts, axis=1).astype(int) result = pd.concat([df, yearly_amounts], axis=1) print(result)
这个方法会直接生成所有需要的年份列,结果和方法一一致。
两种方法都能满足需求,你可以根据自己的数据规模和偏好来选择~
内容的提问来源于stack exchange,提问作者Ismail_FR91
相关产品推荐
相关产品推荐

