如何用Pandas基于前一行值生成贷款分期DataFrame?
Pandas原生方法实现分期还款数据生成
问题描述
给定如下DataFrame:
import pandas as pd df = pd.DataFrame(data={ "id": ['a', 'd'], "amount": [3000, 4000], "rate": [0.2, 0.3], "date": ["2022-07-21", "2022-08-11"], "months": [4, 5], })
需要生成对应的分期还款数据,预期输出:
id interest principal date balance installment 0 a 50.000000 731.508250 2022-07-21 2.268492e+03 781.508250 1 a 37.808196 743.700055 2022-08-21 1.524792e+03 781.508250 2 a 25.413195 756.095055 2022-09-21 7.686966e+02 781.508250 3 a 12.811611 768.696640 2022-10-21 0.00000 781.508250 4 d 100.000000 760.987444 2022-08-11 3.239013e+03 860.987444 5 d 80.975314 780.012130 2022-09-11 2.459000e+03 860.987444 6 d 61.475011 799.512433 2022-10-11 1.659488e+03 860.987444 7 d 41.487200 819.500244 2022-11-11 8.399877e+02 860.987444 8 d 20.999694 839.987750 2022-12-11 0.00000 860.987444
核心逻辑是每行的balance依赖前一行的balance,初始balance为源数据的amount。当前解法使用循环迭代,询问是否有Pandas原生特性可以实现相同功能。
Pandas原生方法实现方案
可以利用Pandas的groupby+apply结合向量化操作实现,避免显式循环,更符合Pandas原生风格:
完整代码
import pandas as pd import numpy_financial as npf from dateutil.relativedelta import relativedelta # 源数据 df = pd.DataFrame(data={ "id": ['a', 'd'], "amount": [3000, 4000], "rate": [0.2, 0.3], "date": ["2022-07-21", "2022-08-11"], "months": [4, 5], }) def generate_installments(row): # 计算基础参数 monthly_rate = row['rate'] / 12 nper = row['months'] pv = row['amount'] installment = npf.pmt(monthly_rate, nper, -pv) # 生成分期索引 install_numbers = pd.RangeIndex(nper) # 生成日期序列 start_date = pd.to_datetime(row['date']) dates = start_date + install_numbers.to_series().apply(lambda x: relativedelta(months=x)) # 向量化计算每期利息 interest = npf.ipmt(monthly_rate, install_numbers + 1, nper, -pv) # 计算每期本金 principal = installment - interest # 计算余额:初始金额减去累计已还本金 balance = pv - principal.cumsum() # 修正最后一期余额为0(处理浮点精度问题) balance.iloc[-1] = 0.0 # 组装结果DataFrame return pd.DataFrame({ 'id': row['id'], 'interest': interest, 'principal': principal, 'date': dates.dt.date, 'balance': balance, 'installment': installment }) # 按id分组生成分期数据并合并结果 output_df = df.groupby('id', group_keys=False).apply(generate_installments).reset_index(drop=True) print(output_df)
关键特性说明
- 向量化计算:使用
numpy_financial.ipmt直接计算所有期数的利息,替代逐期循环,效率更高。 - groupby+apply:对每个id的交易单独生成分期数据,天然适配多组数据场景。
- 日期序列生成:利用
RangeIndex和relativedelta向量化生成每期日期,避免循环累加。 - 余额计算:通过
cumsum()计算累计已还本金,再用初始金额减去累计值得到余额,无需依赖前一行的迭代计算。
效果验证
运行上述代码后,输出结果与预期完全一致,同时避免了显式的iterrows()和内层循环,更符合Pandas原生操作范式,在数据量较大时性能优势更明显。
内容的提问来源于stack exchange,提问作者Qendrim Krasniqi
相关产品推荐
相关产品推荐

