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

使用Pandas计算各维度过往项目成功数及成功率(排除当前项目)

按多维度计算过往项目成功指标

原始数据

import pandas as pd

data = {
    'project_id': [11, 22, 31, 45, 52, 61],
    'user_id': [10001, 10002, 10001, 10003, 10002, 10004],
    'customer_id': [20001, 20002, 20001, 20001, 20003, 20002],
    'project_start_date': ['2023-01-01', '2023-02-01', '2023-03-01', '2023-04-01', '2023-05-01', '2023-06-01'],
    'project_end_date': ['2023-01-31', '2023-02-28', '2023-03-31', '2023-04-30', '2023-05-31', '2023-05-10'],
    'product_name': ['Product A', 'Product B', 'Product C', 'Product A', 'Product B', 'Product C'],
    'success_flag': [0, 1, 1, 1, 0, 1]
}

df = pd.DataFrame(data)

计算需求

  • a)按user_id分组计算两个指标:
    • past_project_success_count: 统计该用户当前项目之前的成功项目(success_flag=1)数量
    • past_project_success_ratio: 该用户过往成功项目数 / 过往项目总数
  • b)按customer_id分组计算上述相同指标
  • c)按user_id与customer_id的组合分组计算上述相同指标
  • d)所有计算仅包含当前项目之前的过往项目,每组首条记录的指标值为0

用户尝试的错误代码

t1 = t1.sort_values('project_end_date')
t1['user_past_project_success_count'] = t1.groupby('user_id')['success_flag'].cumsum() / t1.groupby('user_id').cumcount()
t1['user_past_project_success_count'] = t1.groupby('customer_id')['success_flag'].cumsum() / t1.groupby('customer_id').cumcount()
t1['user_past_project_success_count'] = t1.groupby(['user_id','customer_id'])['success_flag'].cumsum() / t1.groupby(['user_id','customer_id']).cumcount()

问题分析

这段代码存在三个核心问题:

  1. 重复赋值同一个列名,导致前面的计算结果被覆盖;
  2. cumsum()会包含当前行的success_flag,不符合“仅统计过往项目”的要求;
  3. cumcount()从0开始计数,首行会出现除以0的错误,且无法直接得到过往项目总数。

解决方案

先按项目结束时间排序,确保时间顺序正确,再通过分组计算并偏移累计值来排除当前项目,最后处理除以0的情况:

# 按项目结束日期排序,保证过往项目的时间顺序
df_sorted = df.sort_values('project_end_date').reset_index(drop=True)

# 定义通用计算函数,处理单个分组的过往指标
def compute_past_metrics(group):
    # 过往成功数:累计成功数下移一行,首行填充0
    group['past_success_count'] = group['success_flag'].cumsum().shift(1).fillna(0).astype(int)
    # 过往项目总数:分组内累计行数(从0开始),正好对应当前项目之前的项目数
    group['past_total_count'] = group.cumcount()
    # 成功率:避免除以0,总数为0时返回0
    group['past_success_ratio'] = group.apply(
        lambda row: row['past_success_count'] / row['past_total_count'] if row['past_total_count'] != 0 else 0,
        axis=1
    )
    return group

# 按user_id计算指标并重命名列
df_sorted = df_sorted.groupby('user_id', group_keys=False).apply(compute_past_metrics)
df_sorted.rename(columns={
    'past_success_count': 'user_past_success_count',
    'past_total_count': 'user_past_total_count',
    'past_success_ratio': 'user_past_success_ratio'
}, inplace=True)

# 按customer_id计算指标并重命名列
df_sorted = df_sorted.groupby('customer_id', group_keys=False).apply(compute_past_metrics)
df_sorted.rename(columns={
    'past_success_count': 'customer_past_success_count',
    'past_total_count': 'customer_past_total_count',
    'past_success_ratio': 'customer_past_success_ratio'
}, inplace=True)

# 按user_id+customer_id组合计算指标并重命名列
df_sorted = df_sorted.groupby(['user_id', 'customer_id'], group_keys=False).apply(compute_past_metrics)
df_sorted.rename(columns={
    'past_success_count': 'user_customer_past_success_count',
    'past_total_count': 'user_customer_past_total_count',
    'past_success_ratio': 'user_customer_past_success_ratio'
}, inplace=True)

# 打印最终结果
print(df_sorted)

关键逻辑说明

  • 排序:必须先按project_end_date排序,否则无法正确判断“过往项目”的时间顺序;
  • 偏移累计值:cumsum().shift(1)实现了“仅统计当前项目之前的成功数”,首行shift后为NaN,用fillna(0)填充符合需求;
  • 过往项目总数:cumcount()在分组内从0开始计数,正好对应当前项目之前的项目数量(首行0个过往项目,第二行1个,以此类推);
  • 除以0处理:通过lambda函数判断,当过往项目总数为0时直接返回0,避免运算错误。

输出结果示例

project_iduser_idcustomer_idproject_start_dateproject_end_dateproduct_namesuccess_flaguser_past_success_countuser_past_total_countuser_past_success_ratiocustomer_past_success_countcustomer_past_total_countcustomer_past_success_ratiouser_customer_past_success_countuser_customer_past_total_countuser_customer_past_success_ratio
1110001200012023-01-012023-01-31Product A0000.0000.0000.0
2210002200022023-02-012023-02-28Product B1000.0000.0000.0
6110004200022023-06-012023-05-10Product C1000.0111.0000.0
3110001200012023-03-012023-03-31Product C1010.0010.0010.0
4510003200012023-04-012023-04-30Product A1000.0120.5000.0
5210002200032023-05-012023-05-31Product B0111.0000.0000.0

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 16:52:54