
本文介绍如何在 Pandas 中处理含标签列表(如 ['friends', 'family'])的列,实现类似 groupby 的多对一聚合(如按单个标签统计频次、计算均值等),核心方案是使用 explode() 展开再分组,并对比性能更优的纯 Python 替代方法。
本文介绍如何在 pandes 中处理含标签列表(如 `['friends', 'family']`)的列,实现类似 `groupby` 的多对一聚合(如按单个标签统计频次、计算均值等),核心方案是使用 `explode()` 展开再分组,并对比性能更优的纯 python 替代方法。
在实际数据分析中,常遇到“一个样本属于多个类别”的场景,例如商品打标(['electronics', 'sale'])、文章分类(['AI', 'tutorial', 'python'])或用户兴趣标签(['sports', 'music'])。这类数据无法直接用 df.groupby('tags') 分组——因为 tags 列存储的是 Python 列表对象,Pandas 会将整个列表视为单一分组键,而非将其内部元素逐一分解。
✅ 正确做法:先用 explode() 将嵌套标签展开为多行,再执行标准 groupby 操作。这是最通用、可扩展性最强的方案:
import pandas as pd
df = pd.DataFrame({
'Id': ['item1', 'item2', 'item3', 'item4'],
'tags': [['friends','family'], ['friends'], [], ['family','holiday']]
})
# 展开 + 分组计数(推荐用于后续需链式 agg 的场景)
result_count = (df.explode('tags')
.groupby('tags', as_index=False)
.agg(count=('tags', 'size')))
print(result_count)
# tags count
# 0 family 2
# 1 friends 2
# 2 holiday 1
你还可以对其他列做任意聚合,例如获取每个标签关联的 Id 集合(去重)或平均值(若存在数值列):
# 获取每个标签对应的所有 Id(转为 frozenset 便于哈希与去重)
result_ids = (df.explode('tags')
.groupby('tags', as_index=False)
.agg(Id_set=('Id', lambda x: frozenset(x))))
# 若原始数据含数值列(如 'score'),可直接聚合:
# .agg(score_mean=('score', 'mean'), score_std=('score', 'std'))
⚠️ 注意事项:
-
explode()会复制行(如['a','b']→ 两行),当标签数量大或数据量巨大时,内存和计算开销显著上升; - 空列表
[]会被展开为NaN行,若需排除,可在explode后加.dropna(subset=['tags']); -
as_index=False确保返回 DataFrame 而非 Series,便于后续操作。
⚡ 性能优化建议:若仅需统计标签频次(无需关联原始行其他字段),纯 Python 方案更快更省内存:
from collections import Counter
from itertools import chain
tag_counts = Counter(chain.from_iterable(df['tags']))
print(tag_counts) # Counter({'friends': 2, 'family': 2, 'holiday': 1})
# 转为 DataFrame(如需统一输出格式)
pd.DataFrame(list(tag_counts.items()), columns=['tags', 'count'])
? 若目标是像问题中所述,构建一个类似字典的分组映射(如 grpby['friends'] 返回对应子 DataFrame),可用以下简洁方式:
# 构建 {tag: sub_df} 字典(每项为原始结构的子集,不展开行)
tmp = df.assign(group=df['tags']).explode('group')
grouped_dict = {k: v.drop(columns='group') for k, v in tmp.groupby('group')}
# 使用示例
print(grouped_dict['friends'])
# Id tags
# 0 item1 [friends, family]
# 1 item2 [friends]
总结:Pandas 原生 groupby 不支持“一行多组”,但通过 explode() 可无缝桥接该需求;对简单计数优先考虑 Counter + chain;对复杂聚合(如跨列统计、自定义函数)务必使用 explode + groupby 组合——它保持了 Pandas 的表达力与一致性,是生产环境中的标准实践。










