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

如何用groupby和rolling统计患者阳性结果并保留原DataFrame结构?

解决方案

数据预处理

先确保日期格式和阳性结果数值化,同时排序保证窗口计算逻辑正确:

import pandas as pd

# 转换日期列为datetime类型
df['ORDER_INST'] = pd.to_datetime(df['ORDER_INST'])
# 将布尔型阳性结果转为1/0(True→1,False→0)
df['ALL_RESULTS_NUM'] = df['ALL_RESULTS'].astype(int)
# 按患者ID、检测类型、日期排序,确保滚动窗口按时间顺序计算
df = df.sort_values(["PAT_MRN_ID", "TEST_TYPE", "ORDER_INST"])

方法1:Merge方式保留所有字段并添加滚动求和列

单独计算滚动结果后合并回原表,规避索引不匹配问题:

# 计算90天内滚动阳性数,重置索引以便和原表合并
rolling_sum = df.groupby(["PAT_MRN_ID", "TEST_TYPE"]) \
                .rolling('90d', min_periods=2, on='ORDER_INST')['ALL_RESULTS_NUM'] \
                .sum() \
                .reset_index() \
                .rename(columns={'ALL_RESULTS_NUM': 'SUM'})

# 合并回原DataFrame,保留所有原始字段
df = df.merge(rolling_sum, on=["PAT_MRN_ID", "TEST_TYPE", "ORDER_INST"], how='left')

方法2:Apply+索引对齐直接生成新列

通过分组内设置日期为索引,执行滚动计算后对齐原表索引:

# 直接生成SUM列,全程保留原表所有字段
df['SUM'] = df.groupby(["PAT_MRN_ID", "TEST_TYPE"]) \
              .apply(lambda group: 
                     group.set_index('ORDER_INST')['ALL_RESULTS_NUM']
                          .rolling('90d', min_periods=2).sum()) \
              .reset_index(level=[0, 1], drop=True)

移除90天内阳性≥2次的患者

先定位需要移除的患者-检测类型组合,再过滤对应记录:

# 提取存在90天内阳性≥2次的患者-检测类型对
to_remove = df[df['SUM'] >= 2][["PAT_MRN_ID", "TEST_TYPE"]].drop_duplicates()

# 过滤掉这些患者的所有记录
df_clean = df[~df.apply(lambda row: (row['PAT_MRN_ID'], row['TEST_TYPE']) in to_remove.values, axis=1)]

报错原因说明

  1. ValueError: cannot handle a non-unique multi-index!
    你在groupby时使用了as_index=False,导致rolling生成的结果索引与原DataFrame无法对齐,且形成的复合索引不唯一,无法直接赋值到新列。去掉as_index=False并通过reset_index/merge处理即可解决。

  2. ValueError: transform must return a scalar value for each group
    transform要求每个分组返回与组内行数一致的序列或单个标量。你之前的写法中,rolling的on参数在分组子DataFrame中无法正确识别,且返回结构不符合transform的要求。改用apply配合索引重置的方式可以避免这个问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 08:45:21