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

Pandas按两列分组,获取其他列非空唯一值计数及值

分组统计非空唯一值并批量更新分组内容

需求

按vendor和event两列分组,对指定列完成以下操作:

  • 统计非空唯一值的数量
  • 获取逗号分隔的非空唯一值
    后续需实现:当某列分组后的唯一值仅为1个时,更新该分组下所有行的对应列内容。

示例数据

[
  {
    "vendor": "ven1",
    "event": "event",
    "code": "sd",
    "gender": "M",
    "female": "0"
  },
  {
    "vendor": "ven1",
    "event": "event",
    "code": "sd",
    "gender": "M",
    "female": ""
  },
  {
    "vendor": "ven1",
    "event": "event",
    "code": "sd",
    "gender": "M",
    "female": "0"
  },
  {
    "vendor": "ven1",
    "event": "event2",
    "code": "sd",
    "gender": "M",
    "female": "0"
  },
  {
    "vendor": "ven1",
    "event": "event2",
    "code": "sd",
    "gender": "F",
    "female": "0"
  }
]

尝试过的代码

未得到预期输出的分组聚合

result = df.groupby(['vendor', 'event']).agg({
   'code':  ['nunique', 'unique'],
   'gender':  ['nunique', 'unique'],
   'cancel': ['nunique', 'unique'],
   'female':  ['nunique', 'unique'],
   'male':  ['nunique', 'unique']
}).reset_index()

成功获取唯一值计数的代码

result = df.groupby(['vendor', 'event']).agg({
   'code': lambda x: x.nunique(),
   'gender': lambda x: x.nunique(),
   'cancel': lambda x: x.nunique(),
   'female': lambda x: x.nunique(),
   'male': lambda x: x.nunique()
}).reset_index()

解决方案

1. 同时获取非空唯一值计数和逗号分隔的唯一值

原代码的问题在于使用['nunique', 'unique']会生成多层列索引,且未过滤空字符串。以下代码生成扁平化列名,同时处理空值:

import pandas as pd
import numpy as np

# 替换空字符串为NaN,方便后续空值处理
df['female'] = df['female'].replace('', pd.NA)

# 分组聚合,自定义列名区分计数和唯一值
agg_result = df.groupby(['vendor', 'event']).agg(
    code_count=('code', lambda x: x[x != ''].nunique()),
    code_unique=('code', lambda x: ','.join(sorted(x[x != ''].unique()))),
    gender_count=('gender', lambda x: x[x != ''].nunique()),
    gender_unique=('gender', lambda x: ','.join(sorted(x[x != ''].unique()))),
    female_count=('female', lambda x: x.nunique(dropna=True)),
    female_unique=('female', lambda x: ','.join(sorted(x.dropna().unique().astype(str))))
).reset_index()

2. 批量更新分组内的列内容

当某列分组后唯一值仅1个时,将该分组所有行的对应列替换为这个唯一值,有两种实现方式:

方式一:使用transform逐列处理

cols_to_update = ['code', 'gender', 'female']

for col in cols_to_update:
    # 获取分组内的非空唯一值列表
    group_unique = df.groupby(['vendor', 'event'])[col].transform(
        lambda x: x[x != ''].unique() if len(x[x != ''].unique()) > 0 else []
    )
    # 当唯一值数量为1时替换,否则保留原内容
    df[col] = np.where(
        group_unique.apply(len) == 1,
        group_unique.str[0],
        df[col]
    )

方式二:构建映射表合并更新(更高效)

cols_to_update = ['code', 'gender', 'female']

# 构建分组到唯一值的映射,仅保留唯一值数量为1的情况
update_mapping = df.groupby(['vendor', 'event']).agg(
    **{col: lambda x: x[x != ''].unique()[0] if len(x[x != ''].unique()) == 1 else None for col in cols_to_update}
).reset_index()

# 合并映射表到原数据,更新对应列
df = df.merge(update_mapping, on=['vendor', 'event'], suffixes=('', '_new'))
for col in cols_to_update:
    df[col] = df[f'{col}_new'].fillna(df[col])
# 清理临时列
df.drop([f'{col}_new' for col in cols_to_update], axis=1, inplace=True)

内容的提问来源于stack exchange,提问作者Md Parvez Alam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 01:10:18