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

如何基于Match Quality聚合GroupBy结果并处理NaN,lambda能否关联对应列

问题描述

编辑补充:删除NaN行不可行,因为并非所有分组都有Match Quality值,但仍需提取这些分组中的定价数据。

现有如下DataFrame:

import numpy as np
import pandas as pd

df = pd.DataFrame({
    'Part Description':['Clutch Set', 'Clutch Set', 'Clutch Set', 'Clutch Set', 'Cambelt Kit', 'Cambelt Kit', 'Cambelt Kit', 'Cambelt Kit', 'Front Bumper', 'Front Bumper'],
    'Price':[100, np.nan, np.nan, 50, 1000, np.nan, 500, np.nan, 250, np.nan],
    'Match Quality':['Poor', np.nan, np.nan, np.nan, np.nan, np.nan, 'Perfect', np.nan, np.nan, np.nan]
})

需求:按Part Description分组并聚合Price列,规则为:

  • 优先选择Match Quality非空对应的Price值;
  • 若分组内Match Quality全为NaN,则选择该分组的最高Price值。

期望输出结果:

pd.DataFrame({
    'Part Description':['Clutch Set', 'Cambelt Kit', 'Front Bumper'],
    'Price':[100, 500, 250],
    'Match Quality':['Poor', 'Perfect', np.nan]
})

尝试用aggregate结合lambda函数实现,但不确定能否在lambda中引用Price对应的Match Quality值:

df.groupby(['Part Description']).agg(lambda x: ... )
解决方案

直接用agg的lambda单独处理Price列时,无法直接引用同一行的Match Quality值——因为lambda接收的是单列的Series,只能访问当前列的数据。推荐用groupby.apply实现,它能让你拿到整个分组的DataFrame,可同时操作多列,逻辑更清晰:

def process_group(group):
    # 筛选出Match Quality非空的行
    match_rows = group[group['Match Quality'].notna()]
    if not match_rows.empty:
        # 取第一个有效匹配的Price和Match Quality(若有多条可按需调整规则)
        return pd.Series({
            'Price': match_rows['Price'].iloc[0],
            'Match Quality': match_rows['Match Quality'].iloc[0]
        })
    else:
        # 分组无有效匹配时,取最高Price,Match Quality设为NaN
        return pd.Series({
            'Price': group['Price'].max(),
            'Match Quality': np.nan
        })

# 应用分组处理并重置索引
result = df.groupby('Part Description').apply(process_group).reset_index()
print(result)

输出结果:

Part Description  Price Match Quality
0      Cambelt Kit  500.0        Perfect
1      Clutch Set  100.0           Poor
2   Front Bumper  250.0            NaN

如果一定要用agg,可以先构造临时列打包Price和Match Quality,再对元组列聚合,但可读性较差:

# 构造包含Price和Match Quality的元组列
df['price_match'] = df.apply(lambda row: (row['Price'], row['Match Quality']), axis=1)

def agg_func(tuples):
    # 过滤出Match Quality非空的元组
    valid_tuples = [t for t in tuples if pd.notna(t[1])]
    if valid_tuples:
        return valid_tuples[0]
    else:
        # 取Price最大值对应的元组
        max_price = max([t[0] for t in tuples if pd.notna(t[0])])
        return (max_price, np.nan)

# 聚合后拆分元组为列
result = df.groupby('Part Description')['price_match'].agg(agg_func)\
           .apply(pd.Series)\
           .rename(columns={0:'Price', 1:'Match Quality'})\
           .reset_index()

对比来看,groupby.apply的方式逻辑更直观,后续维护也更方便。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 17:27:26