如何在分组DataFrame中自定义统计出现次数及优化列拼接
问题描述
输入示例
Id Values Status 0 Id001 red online 1 Id002 brown running 2 Id002 white off 3 Id003 blue online 4 Id003 green valid 5 Id003 yellow running 6 Id004 rose off 7 Id004 purple off
输出示例
Id Values Status Id_occ Val_occ Sta_occ 0 Id001 red online 1 1 1 1 Id002 brown|white running|off 2 2 2 2 Id003 blue|green|yellow online|valid|running 3 3 3 3 Id004 rose|purple off 2 2 1
我已经实现了Values和Status列的拼接,但不知道怎么生成Id_occ、Val_occ、Sta_occ这三个出现次数统计列。另外,有没有更高效的方式生成拼接后的Values和Status列?
现有代码
import pandas as pd df = pd.DataFrame({'Id': ['Id001', 'Id002', 'Id002', 'Id003', 'Id003', 'Id003', 'Id004', 'Id004'], 'Values': ['red', 'brown','white','blue', 'green', 'yellow', 'rose', 'purple'], 'Status': ['online', 'running', 'off', 'online', 'valid', 'running', 'off', 'off']}) out = (df.groupby(['Id']) .agg({'Values': 'unique', 'Status': 'unique'}) .applymap(lambda x: '|'.join([str(val) for val in list(x)])) .reset_index() )
解决方案
一、更优的列拼接方式
你当前的实现逻辑可行,但可以直接在聚合阶段完成拼接+去重的操作,省去后续的applymap步骤,代码更简洁高效:
# 直接在agg中完成去重拼接 agg_funcs = { 'Values': lambda x: '|'.join(pd.unique(x)), 'Status': lambda x: '|'.join(pd.unique(x)) }
如果不需要去重(保留原始重复值),直接用'|'.join(x)即可,无需pd.unique。
二、生成统计列的方法
三个统计列的定义:
Id_occ:对应Id在原始数据中的总出现次数Val_occ:对应Id下去重后Values的数量Sta_occ:对应Id下去重后Status的数量
可以通过一次分组聚合完成所有计算,避免多次遍历数据:
# 扩展聚合函数,包含拼接和统计逻辑 agg_funcs = { 'Values': [lambda x: '|'.join(pd.unique(x)), lambda x: len(pd.unique(x))], 'Status': [lambda x: '|'.join(pd.unique(x)), lambda x: len(pd.unique(x))], 'Id': 'count' # 统计Id出现的总次数 }
完整代码
import pandas as pd df = pd.DataFrame({'Id': ['Id001', 'Id002', 'Id002', 'Id003', 'Id003', 'Id003', 'Id004', 'Id004'], 'Values': ['red', 'brown','white','blue', 'green', 'yellow', 'rose', 'purple'], 'Status': ['online', 'running', 'off', 'online', 'valid', 'running', 'off', 'off']}) # 定义聚合规则 agg_funcs = { 'Values': [lambda x: '|'.join(pd.unique(x)), lambda x: len(pd.unique(x))], 'Status': [lambda x: '|'.join(pd.unique(x)), lambda x: len(pd.unique(x))], 'Id': 'count' } # 执行聚合并整理列名和顺序 out = df.groupby('Id').agg(agg_funcs) out.columns = ['Values', 'Val_occ', 'Status', 'Sta_occ', 'Id_occ'] out = out.reset_index()[['Id', 'Values', 'Status', 'Id_occ', 'Val_occ', 'Sta_occ']] print(out)
运行后输出与示例完全一致:
Id Values Status Id_occ Val_occ Sta_occ 0 Id001 red online 1 1 1 1 Id002 brown|white running|off 2 2 2 2 Id003 blue|green|yellow online|valid|running 3 3 3 3 Id004 rose|purple off 2 2 1
内容的提问来源于stack exchange,提问作者user19956605
相关产品推荐
相关产品推荐

