You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Pandas的groupby().agg()后选取首个非NaN值?

问题描述

我编写了如下代码:

df.groupby(["id", "year"], as_index=False).agg({"brand":"first", "color":"first"})

但数据中存在部分NaN值,我希望选取分组后各字段的首个非NaN值。

示例DataFrame如下:

idyearbrandcolor
0012010NaNBlue
0012010AudiNaN
0012010AudoBlue
0012011BmwNaN
0012011NaNNaN
0012012BMWGreen
0022010TeslaWhite

我需要按id和year的唯一组合分组(即df.groupby(["id", "year"])),获取每个字段的首个有效数据。数据集庞大且杂乱,存在大量缺失值和拼写错误(示例已模拟),拼写错误将另行处理,当前只需获取分组后的首个非空值。

期望输出:

idyearbrandcolor
0012010AudiBlue
0012011BmwNaN
0012012BMWGreen
0022010TeslaWhite
解决方案

原代码中使用的"first"聚合规则会直接返回分组内列的第一个元素,哪怕该元素是NaN,无法满足需求。可以通过以下几种方式实现“取首个非NaN值”:

方法1:自定义聚合函数(可读性高)

定义一个函数筛选非空值后取第一个,全为空则返回NaN:

import pandas as pd
import numpy as np

def first_non_null(series):
    non_null_values = series.dropna()
    return non_null_values.iloc[0] if not non_null_values.empty else np.nan

# 应用分组聚合
result = df.groupby(["id", "year"], as_index=False).agg({
    "brand": first_non_null,
    "color": first_non_null
})

方法2:Lambda表达式(简洁快速)

无需单独定义函数,直接在agg中使用lambda逻辑:

result = df.groupby(["id", "year"], as_index=False).agg({
    "brand": lambda x: x.dropna().iloc[0] if not x.dropna().empty else np.nan,
    "color": lambda x: x.dropna().iloc[0] if not x.dropna().empty else np.nan
})

方法3:利用first_valid_index(更高效)

借助Pandas Series的first_valid_index()方法定位首个非空值的位置,再取值:

result = df.groupby(["id", "year"], as_index=False).agg({
    "brand": lambda x: x[x.first_valid_index()] if x.first_valid_index() is not None else np.nan,
    "color": lambda x: x[x.first_valid_index()] if x.first_valid_index() is not None else np.nan
})

以上三种方法均可实现需求,其中方法1适合需要重复使用的场景,方法2、3适合快速实现。

内容的提问来源于stack exchange,提问作者Xtiaan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 06:16:08