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

如何在Pandas中对重叠独热编码的分类数据进行分组?

问题描述

我有一个包含游戏评分和媒体曝光分类数据的数据集,简化示例如下:

import pandas as pd

df = pd.DataFrame(
    {'titleName': ['game_A', 'game_B', 'game_C', 'game_D'],
    'reviewScore': [88.1, 70.3, 91.3, 66.1],
    'mediaAppearances': [['Pub_A', 'Pub_C'], ['Pub_B'], ['Pub_B', 'Pub_C'], ['Pub_A', 'Pub_B', 'Pub_C']]}
)

其中mediaAppearances是多值分类特征,记录游戏是否出现在某出版商的报道中。我对该特征做了独热编码,生成各出版商的离散布尔列(游戏出现在该出版商报道中则为1,否则为0):

final_df = pd.concat([df,pd.get_dummies(df['mediaAppearances'].apply(pd.Series).stack()).groupby(level=0).sum()], axis=1)

生成的DataFrame如下:

titleNamereviewScoremediaAppearancesPub_APub_BPub_C
game_A88.1"Pub_A, Pub_C"101
game_B70.3"Pub_B"010
game_C91.3"Pub_B, Pub_C"011
game_D66.1"Pub_A, Pub_B, Pub_C"111

我希望按每个出版商分组,分析其报道过的游戏的reviewScore,最终得到对应三个出版商的分组结果,方便做聚合分析。

目前我可以通过循环单独过滤每个出版商的数据来计算统计量:

for publisher in ['Pub_A', 'Pub_B', 'Pub_C']:
    _mean = final_df[final_df[publisher] == True]['reviewScore'].mean()
    print(f"Mean reviewScore for games appearing in {publisher}: {_mean:.1f}")

输出:

Mean reviewScore for games appearing in Pub_A: 77.1  
Mean reviewScore for games appearing in Pub_B: 75.9  
Mean reviewScore for games appearing in Pub_C: 81.8

但这种方法只适合计算单一统计量,当需要使用自定义聚合函数、同时分析多个统计量(比如用pandas的describe函数)或者快速切换分组变量时,流程会很繁琐。

我尝试过用标准的groupby语法,但由于独热编码后的出版商列不互斥,分组后会生成所有True/False组合的冗余结果:

final_df.groupby(['Pub_A', 'Pub_B', 'Pub_C']).describe().reset_index()

输出结果包含各种组合的分组,并非我想要的按单个出版商维度的聚合。

我想知道是否有办法用groupby查询生成单个分组DataFrame,能直接对整个数据框应用聚合函数,而不用逐个过滤数据?比如能否通过查询得到如下用describe生成的结果:

Publishercountmeanstdmin25%50%75%max
Pub_A2.077.115.666.171.677.182.688.1
Pub_B3.075.913.566.168.270.380.891.3
Pub_C3.081.813.766.177.188.189.791.3

解决方案

可以通过**将独热编码的出版商列转换为长格式(long format)**来实现按单个出版商分组的需求,具体步骤如下:

  1. 提取出版商相关列和评分列,将出版商列转置为行,保留对应的评分数据
  2. 过滤出值为1的行(即游戏被该出版商报道的记录)
  3. 按出版商分组后应用聚合函数

具体代码如下:

# 提取需要的列:出版商列和reviewScore
pub_cols = ['Pub_A', 'Pub_B', 'Pub_C']
temp_df = final_df[['reviewScore'] + pub_cols]

# 将出版商列转为长格式,重置索引
melted = temp_df.melt(id_vars='reviewScore', var_name='Publisher', value_name='IsPresent')

# 过滤出被报道的记录(IsPresent=1),然后分组聚合
result = melted[melted['IsPresent'] == 1].groupby('Publisher')['reviewScore'].describe()

# 调整列名和格式(可选,让结果更贴合需求)
result = result.round(1).reset_index()

运行上述代码后,得到的result就是你想要的按单个出版商聚合的统计结果:

Publishercountmeanstdmin25%50%75%max
Pub_A2.077.115.666.171.677.182.688.1
Pub_B3.075.913.566.168.270.380.891.3
Pub_C3.081.813.766.177.188.189.791.3

代码解释

  • melt函数将宽格式的出版商列转为长格式,每条记录对应一个游戏-出版商的关系
  • 过滤IsPresent=1的行,只保留被该出版商报道的游戏记录
  • 直接按Publisher分组后调用describe(),就能一次性得到所有统计量,也可以替换成自定义聚合函数(比如agg(['mean', 'median', 'std']))

这种方法既符合Pandas的标准语法,又能灵活支持各种聚合需求,无需逐个处理每个出版商。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 01:55:35