Pandas分组处理求助:提取最新逾期金额时返回全NaN如何解决?
问题分析与解决方案
你的代码返回全NaN的核心问题是索引不匹配:
- 当你执行
df_account[df_account["AccountRating"]=='Delayed'].groupby('Debtor ID')["AccountRatingDate"].idxmax()时,返回的是原DataFrame的行位置索引(比如默认的0、1、3这类数字) - 而你的
new_df索引是Debtor ID字符串(比如"约翰·斯诺"),直接赋值时Pandas会按索引对齐,两边索引完全不匹配,所以所有值都变成了NaN。
另外,原代码也没处理那些没有延迟记录的债务人(萨拉·帕克、爱德华·霍尔),这部分需要填充0。
下面给你两种可行的解决方案:
方案1:修正索引对齐问题,合并后填充缺失值
先提取延迟记录的最新值,手动对齐索引后合并到new_df,再用0填充无延迟记录的条目:
# 1. 筛选延迟记录,获取每个债务人最新延迟记录的原行索引 delayed_latest_idx = df_account[df_account["AccountRating"] == "Delayed"]\ .groupby("Debtor ID")["AccountRatingDate"].idxmax() # 2. 提取对应金额,并将结果的索引设置为Debtor ID(方便后续合并) delayed_latest = df_account.loc[delayed_latest_idx, ["AmountOutstanding", "AmountPastDue"]] delayed_latest.index = df_account.loc[delayed_latest_idx, "Debtor ID"] # 3. 重命名列并合并到new_df,用0填充缺失值 new_df = new_df.join( delayed_latest.rename(columns={ "AmountOutstanding": "TheMostRecentOutstanding", "AmountPastDue": "TheMostRecentPastDue" }) ).fillna(0)
方案2:一次性分组聚合(更简洁高效)
直接通过groupby的聚合逻辑,一次性计算所有需要的统计字段,避免索引问题:
# 定义一个辅助函数,获取每组的最新延迟金额(无延迟则返回0) def get_latest_delayed(group): delayed = group[group["AccountRating"] == "Delayed"] if not delayed.empty: latest = delayed.sort_values("AccountRatingDate", ascending=False).iloc[0] return latest["AmountOutstanding"], latest["AmountPastDue"] return 0, 0 # 分组聚合所有字段 new_df = df_account.groupby("Debtor ID").apply(lambda g: pd.Series({ "Incidents of delay": (g["AmountPastDue"] > 0).sum(), "TheMostRecentOutstanding": get_latest_delayed(g)[0], "TheMostRecentPastDue": get_latest_delayed(g)[1] })).reset_index()
执行任意一种方案后,你就能得到期望的结果:
| Debtor ID | Incidents of delay | TheMostRecentOutstanding | TheMostRecentPastDue |
|---|---|---|---|
| 约翰·斯诺 | 2 | 6000 | 300 |
| 萨拉·帕克 | 0 | 0 | 0 |
| 爱德华·霍尔 | 0 | 0 | 0 |
| 道格拉斯·科尔 | 2 | 1000 | 400 |
内容的提问来源于stack exchange,提问作者user9695260
相关产品推荐
相关产品推荐

