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

如何基于条件按ID统计Pandas中列值的组合情况?

按ID分组统计符合多条件的记录数解决方案

数据集

首先初始化测试数据集:

import pandas as pd

data=[['id1','bla bla word1', 10], ['id1','bla bla word2', 12], ['id1','bla bla', 10], ['id2','bla bla', 10], ['id2','bla bla bla123', 11] , ['id3','bla bla word1', 22],
      ['id4','bla bla word1', 22], ['id4','bla bla nicebla', 2], ['id5','bla bla word2', 22], ['id5','bla bla word2', 22], ['id6','bla bla word2', 22],['id6','bla bla bla22', 112],
     ['id7','bla bla word2', 17],['id7','bla bla word1', 19]]
df_test=pd.DataFrame(data, columns=['id', 'search_word', 'value'])

生成的DataFrame结构如下:

id  search_word  value
0   id1  bla bla word1    10
1   id1  bla bla word2    12
2   id1  bla bla          10
3   id2  bla bla          10
4   id2  bla bla bla123   11
5   id3  bla bla word1    22
6   id4  bla bla word1    22
7   id4  bla bla nicebla   2
8   id5  bla bla word2    22
9   id5  bla bla word2    22
10  id6  bla bla word2    22
11  id6  bla bla bla22   112
12  id7  bla bla word2    17
13  id7  bla bla word1    19

需求说明

需要将ID按以下7种分组规则统计记录数:

  • group1:仅包含含word1或word2的行的ID(示例:id7)
  • group2:同时包含含word1/word2的行及其他行的ID(示例:id1)
  • group3:仅包含含word1的行的ID(示例:id3)
  • group4:同时包含含word1的行及其他行的ID(示例:id4)
  • group5:仅包含含word2的行的ID(示例:id5)
  • group6:同时包含含word2的行及其他行的ID(示例:id6)
  • group7:仅包含不含word1和word2的行的ID(示例:id2)

问题背景

尝试用df_test[(df_test['search_word'].str.contains('word1|word2')).groupby(df_test["id"]).transform('all')]处理group1时,返回结果包含了group3、group5的记录,无法精准区分group1;但该方法可用于group3和group5,需找到统一方法覆盖所有分组。

统一解决方案

通过为每个ID生成特征标记,再基于特征进行分组判断,可一次性完成所有分组统计:

步骤1:标记单条记录的特征

为每条记录标记是否包含word1、word2或两者都不包含(即其他内容):

df_test['has_word1'] = df_test['search_word'].str.contains('word1')
df_test['has_word2'] = df_test['search_word'].str.contains('word2')
df_test['has_other'] = ~df_test['has_word1'] & ~df_test['has_word2']

步骤2:按ID聚合特征

对每个ID,统计是否存在含word1、word2或其他内容的记录:

id_features = df_test.groupby('id').agg(
    any_word1=('has_word1', 'any'),
    any_word2=('has_word2', 'any'),
    any_other=('has_other', 'any')
).reset_index()

步骤3:为ID分配分组

根据每个ID的特征组合,判断其所属分组:

def assign_group(row):
    w1, w2, other = row['any_word1'], row['any_word2'], row['any_other']
    if not other:
        # 无其他内容,仅含word1/word2
        if w1 and w2:
            return 'group1'
        elif w1:
            return 'group3'
        elif w2:
            return 'group5'
    else:
        # 有其他内容
        if w1 and w2:
            return 'group2'
        elif w1:
            return 'group4'
        elif w2:
            return 'group6'
        else:
            return 'group7'

id_features['group'] = id_features.apply(assign_group, axis=1)

步骤4:统计分组结果

分别统计每个组的ID数量和对应记录数:

# 统计每个组的ID数量
group_id_count = id_features.groupby('group').size().reset_index(name='id_count')
# 统计每个组的记录数
df_with_group = df_test.merge(id_features[['id', 'group']], on='id')
group_record_count = df_with_group.groupby('group').size().reset_index(name='record_count')
# 合并统计结果
final_stats = pd.merge(group_id_count, group_record_count, on='group')
print(final_stats)

运行结果

group  id_count  record_count
0  group1         1             2
1  group2         1             3
2  group3         1             1
3  group4         1             2
4  group5         1             2
5  group6         1             2
6  group7         1             2

结果完全匹配需求:

  • group1对应id7(2条记录)
  • group2对应id1(3条记录)
  • group3对应id3(1条记录)
  • group4对应id4(2条记录)
  • group5对应id5(2条记录)
  • group6对应id6(2条记录)
  • group7对应id2(2条记录)

原方法问题解析

之前处理group1的方法返回结果过多,是因为transform('all')会保留所有全组行都含word1/word2的ID记录,这包含了group1、group3、group5的所有数据。通过新增特征判断ID是否同时包含word1和word2,就能精准区分这三个分组。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 15:37:40