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

如何在Pandas中按用户分组计算累计未赴约数并从0起始

问题描述

我有如下Pandas DataFrame(不含最后一列):

name        day   show-in-appointment     previous-missed-appointments
0  Jack   2020/01/01   show                              0
1  Jack   2020/01/02   no-show                           0
2  Jill   2020/01/02   no-show                           0 
3  Jack   2020/01/03   show                              1
4  Jill   2020/01/03   show                              1
5  Jill   2020/01/04   no-show                           1
6  Jack   2020/01/04   show                              1
7  Jill   2020/01/05   show                              2
8  jack   2020/01/06   no-show                           1
9  jack   2020/01/07   show                              2

需要添加名为previous-missed-appointments的列,该列为每个用户此前未赴约(no-show)的累计次数,且每个用户的计数从0开始。可复现的数据集代码如下:

import pandas as pd
import numpy as np

df = pd.DataFrame(
    data=np.asarray([
        ['Jack', 'Jack', 'Jill', 'Jack', 'Jill', 'Jill', 'Jack', 'Jill', 'jack', 'jack'],
        [
            '2020/01/01',
            '2020/01/02',
            '2020/01/02',
            '2020/01/03',
            '2020/01/03',
            '2020/01/04',
            '2020/01/04',
            '2020/01/05',
            '2020/01/06',
            '2020/01/07',
        ],
        ['show', 'no-show', 'no-show', 'show', 'show', 'no-show', 'show', 'show', 'no-show', 'show'],
    ]).T,
    columns=['name', 'day', 'show-in-appointment'],
)

我尝试了多种df.groupby和df.agg(lambda x: cumsum(x))的组合,但均未成功。

解决方案

要实现需求,需抓住三个核心要点:统一用户名大小写避免分组错误、按用户+日期排序保证时间顺序、排除当前行计算累计次数。具体步骤如下:

1. 统一用户名大小写

将name列转换为小写(或大写),消除大小写差异导致的分组偏差:

df['name'] = df['name'].str.lower()

2. 按用户和日期排序

将日期转为datetime格式后,按用户+日期排序,确保累计计数是按时间顺序计算的:

df['day'] = pd.to_datetime(df['day'])
df = df.sort_values(by=['name', 'day']).reset_index(drop=True)

3. 计算此前未赴约累计次数

先将show-in-appointment转为二进制标识(no-show记为1,其余为0),再对每个用户分组计算移位后的累计和——用shift(1)排除当前行的记录,初始空缺值填充0:

# 生成no-show标识列
df['is_no_show'] = (df['show-in-appointment'] == 'no-show').astype(int)

# 分组计算此前累计未赴约次数
df['previous-missed-appointments'] = df.groupby('name')['is_no_show'].cumsum().shift(1).fillna(0).astype(int)

# 可选:删除中间生成的临时列
df = df.drop(columns=['is_no_show'])

最终结果

运行上述代码后,得到的DataFrame与预期完全匹配:

name        day show-in-appointment  previous-missed-appointments
0  jack 2020-01-01                show                              0
1  jack 2020-01-02             no-show                              0
2  jack 2020-01-03                show                              1
3  jack 2020-01-04                show                              1
4  jack 2020-01-06             no-show                              1
5  jack 2020-01-07                show                              2
6  jill 2020-01-02             no-show                              0
7  jill 2020-01-03                show                              1
8  jill 2020-01-04             no-show                              1
9  jill 2020-01-05                show                              2

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 20:15:17