pandas统计子组间元素共现频次的实现、优化与报错解决
Pandas 跨分组异源Name共现统计实现问题
初始问题描述
我有如下一个多层索引(multi-index)Series:
(multi-index) | Count | Group | Source | Name | ______________________________________ A | X | Jolly | 2 | | Stone | 1 | Y | Sand | 1 B | X | Sand | 1 | Y | Beach | 1
我同时持有生成上述Series的原始DataFrame,结构如下:
Group | Source | Name ___________________________ A | X | Jolly A | X | Stone A | X | Jolly A | Y | Sand B | X | Sand B | X | Beach B | Y | Stone
数据满足如下规则:
- 每个
Group下一定同时存在Source为X和Y的条目 - 同一Group内X、Y对应的
Name无重叠:即同一Group下,若某个Name出现在Source=X的条目中,就不会出现在Source=Y的条目中
我的需求是统计同一Group内、不同Source下的Name两两共同出现的次数:例如在Group A中,Source=X下Jolly出现2次、Stone出现1次,对应Source=Y下的Name为Sand;如果跨Group观察到来自不同Source的两个Name频繁共现,即可推断二者指向同一实体。需要基于pandas实现该统计,暂无固定预期输出格式,类似如下交叉统计矩阵即可:
Y Stone | Sand | Beach | Water Stone NaN 1 NaN NaN X Sand 1 NaN NaN NaN ... ... ... ... ...
EDIT #1:现有实现性能不足
我基于已有回答写出了如下实现代码:
def get_source_grouped_combos(df): src_x = df[df['Source'] == 'X'].groupby('Name').count() src_y = df[df['Source'] == 'Y'].groupby('Name').count() return list(product(src_x.index.values, src_y.index.values)) ((dfex.loc[dfex['Group'].map( dfex.groupby(['Group','Source'])['Name'] .agg(set) .groupby(level=0) .agg(lambda x: len(set.intersection(*x))==0))]) .groupby(['Group'])[['Source','Name']] .apply(get_source_grouped_combos) .explode('Name') .agg(set) .value_counts() )
代码在示例数据上运行后得到如下输出:
{Sand, Stone} 2 {Jolly, Sand} 1 {Beach, Stone} 1 dtype: int64
但该实现使用apply方法运行速度较慢,需要性能更优的实现方案。
EDIT #2:实际数据集运行报错
我将上述代码应用到实际数据集(各列数据类型dtype与示例完全一致)时,代码最后两行:
.agg(set) .value_counts()
抛出如下错误:
AttributeError: 'set' object has no attribute 'value_counts'
排查发现.agg(set)会将整个Series包装为一个集合,而非对Series中的每个值逐元素执行集合转换,需要修复该问题,以实现对每个Name集合的出现频次统计。
EDIT #3:NaN值引发异常的原因疑问
我进一步排查发现该问题由数据中存在NaN值引发,想了解为何当Series中存在NaN值时,.agg(set)会将整个Series转为单个集合,而非对每个元素逐元素执行转换?
内容的提问来源于stack exchange,提问作者Verbal_Kint
相关产品推荐
相关产品推荐

