如何使用Pandas按客户和月份计算信贷还款总和、剩余本金及累计信贷额?
如何使用Pandas按客户和月份计算信贷还款总和、剩余本金及累计信贷额?
看起来你现在的问题是没把每笔信贷的还款周期展开,只统计了放款月份的信贷数据,所以没法得到逐月的还款指标。我来一步步帮你实现你想要的结果:
先明确需求逻辑
每笔信贷的还款是从放款月份的下一个月开始,连续还duration个月,每个月固定还installment金额。我们需要:
total_sum:当月该客户所有还款金额的拼接(用+连接)sum_cred:该客户当前剩余的总本金(所有信贷还清后变为0)total_inv:剩余本金的计算表达式(用初始总信贷额依次减去各月的还款总和)
步骤1:展开每笔信贷的还款月份
首先要把每笔信贷的还款周期拆成逐月的记录,这样才能按月份聚合:
import pandas as pd # 你的原始数据 creditos = pd.DataFrame({ "id_customer": ["A", "B", "A"], "id_credit":[1001, 1002, 1003], "duration": [4,3,5], "date": ["2022-01-02", "2022-02-03", "2022-03-04"], "credit": [100, 90, 250], "installment": [25,30,50], }) # 转换日期格式,计算还款起始月份(放款月+1) creditos["date"] = pd.to_datetime(creditos["date"]) creditos['start_month'] = creditos['date'].dt.to_period('M') + 1 # 为每笔信贷生成连续的还款月份序列 creditos['repayment_months'] = creditos.apply( lambda row: pd.period_range(start=row['start_month'], periods=row['duration'], freq='M'), axis=1 ) # 展开成逐月的还款记录 repayments = creditos.explode('repayment_months').rename(columns={'repayment_months': 'month'})
这一步后,repayments里会有每笔信贷对应的每个还款月的记录,比如客户A的1001信贷会生成Feb-2022到May-2022的4条记录,每条记录的installment都是25。
步骤2:计算当月还款总和total_sum
按客户和月份分组,把当月的还款金额用+拼接起来:
total_sum_df = repayments.groupby(['id_customer', 'month'])['installment'].agg( lambda x: '+'.join(map(str, x)) ).reset_index().rename(columns={'installment': 'total_sum'})
步骤3:计算剩余总本金sum_cred
我们需要跟踪每笔信贷在每个还款月的剩余本金,再按客户和月份求和:
# 计算每笔信贷在当前还款月的已还次数 repayments['repay_count'] = repayments.groupby('id_credit')['month'].cumcount() + 1 # 计算单笔信贷的剩余本金,低于0时设为0 repayments['remaining'] = (repayments['credit'] - repayments['installment'] * repayments['repay_count']).clip(lower=0) # 按客户和月份求和剩余本金,得到sum_cred sum_cred_df = repayments.groupby(['id_customer', 'month'])['remaining'].sum().reset_index().rename(columns={'remaining': 'sum_cred'})
步骤4:生成剩余本金表达式total_inv
这里我们用总信贷额依次减去各月的还款总和,生成你想要的表达式:
# 计算每个客户每月的还款总额(数值) monthly_pay = repayments.groupby(['id_customer', 'month'])['installment'].sum().reset_index().rename(columns={'installment': 'monthly_pay'}) # 计算每个客户的总信贷额 total_credit = creditos.groupby('id_customer')['credit'].sum().reset_index().rename(columns={'credit': 'total_credit'}) # 合并总信贷额,并生成表达式 monthly_pay = pd.merge(monthly_pay, total_credit, on='id_customer') monthly_pay['total_inv'] = monthly_pay.apply( lambda row: f"{row['total_credit']}-{'-'.join(map(str, monthly_pay[(monthly_pay['id_customer'] == row['id_customer']) & (monthly_pay['month'] <= row['month'])]['monthly_pay']))}", axis=1 )
步骤5:合并所有结果并格式化
最后把所有指标合并,再把月份格式改成你想要的缩写:
# 合并所有数据框 final_df = pd.merge(total_sum_df, sum_cred_df, on=['id_customer', 'month']) final_df = pd.merge(final_df, monthly_pay[['id_customer', 'month', 'total_inv']], on=['id_customer', 'month']) # 把月份转为缩写(比如2022-02 → Feb) final_df['month'] = final_df['month'].dt.strftime('%b') # 调整列顺序 final_df = final_df[['id_customer', 'month', 'total_sum', 'total_inv', 'sum_cred']] print(final_df)
运行后得到的结果和你期望的输出几乎一致,如果你需要调整total_inv的表达式逻辑(比如按单笔信贷的还款来拼接),可以在步骤4里修改表达式的生成方式。
备注:内容来源于stack exchange,提问作者Vanessa
相关产品推荐
相关产品推荐

