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

如何用Pandas按供应商与周计算通过率并生成含对应列的新DataFrame?

问题描述

现有如下结构的DataFrame:

Vendor  GRDate  Pass/Fail
0   204177  2022-22 1.0
1   204177  2022-22 0.0
2   204177  2022-22 0.0
3   204177  2022-22 1.0
4   204177  2022-22 1.0
5   204177  2022-22 1.0
7   201645  2022-22 0.0
8   201645  2022-22 0.0
9   201645  2022-22 1.0
10  201645  2022-22 1.0

需求:按Vendor和GRDate分组,计算每组中Pass/Fail等于1的通过率(通过数/总条数),生成包含Vendor、GRDate、Performance列的新DataFrame,预期结果如下:

Vendor  GRDate  Performance
0   204177  2022-22 0.6
1   201645  2022-22 0.5

尝试的代码如下:

sdp_percent = sdp.groupby(['GRDate','Vendor'])['Pass/Fail'].apply(lambda x: x[x == 1].count()) / sdp.groupby(['GRDate','Vendor'])['Pass/Fail'].count()

遇到的问题:

  • 上述代码仅返回通过率数值,Vendor和GRDate作为索引存在而非显式列,看起来像是丢失了;
  • 若给两个groupby结果都添加.reset_index(),会报错:unsupported operand type(s) for /: 'str' and 'str'
问题分析与解决

问题根源

  1. 两次独立执行groupby后做除法,得到的是带MultiIndex的Series:GRDate和Vendor是索引层级,不是显式列,所以看起来像是丢失了这两列;
  2. 若给两个groupby结果都执行reset_index(),会得到两个包含GRDate、Vendor、Pass/Fail列的DataFrame,此时做除法会尝试对所有列进行运算——但GRDate和Vendor是字符串类型,无法参与除法,因此触发类型错误。

正确实现方式

方法1:利用均值直接计算(最简洁)

由于Pass/Fail列是1(通过)和0(失败)的数值型数据,分组后的均值恰好等于通过率(通过数/总条数),写法如下:

sdp_percent = sdp.groupby(['GRDate', 'Vendor'])['Pass/Fail'].mean().reset_index(name='Performance')

方法2:单次groupby内完成计算

通过apply在分组内一次性计算通过率,避免两次groupby的冗余操作:

sdp_percent = sdp.groupby(['GRDate', 'Vendor'])['Pass/Fail'].apply(lambda x: x[x == 1].count() / len(x)).reset_index(name='Performance')

方法3:使用agg聚合函数

通过agg分别统计通过数和总数,再计算比率:

agg_result = sdp.groupby(['GRDate', 'Vendor'])['Pass/Fail'].agg(
    pass_count=lambda x: x[x == 1].count(),
    total_count='count'
).reset_index()
sdp_percent = agg_result.assign(Performance=agg_result['pass_count'] / agg_result['total_count'])[['Vendor', 'GRDate', 'Performance']]

以上三种方法均可得到符合预期的DataFrame,其中方法1最为高效简洁。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 22:05:55