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

Pandas中条件计数向量化优化方案咨询

优化Pandas 30天再入院次数统计的向量化方案

嘿,我懂你想通过向量化提升30天再入院次数统计性能的痛点——df.rolling().apply确实经常因为不是真正的向量化执行,在数据量大的时候拖慢速度。咱们从数据预处理开始,一步步给出高效的解决方案。

第一步:数据预处理

首先得把你的模拟数据转换成规范的DataFrame,重点是把日期列转成datetime类型,并且按患者ID和就诊日期排序,确保后续计算的时间顺序正确:

import pandas as pd

# 模拟你的原始数据
data = {
    'ID': [1, 1, 2, 3, 3],
    'VISIT_NO': [1, 2, 1, 1, 2],
    'ARRIVED': ['29/02/1996', '01/12/1996', '20/09/1996', '27/06/1996', '04/07/1996'],
    'LEFT': ['01/03/1996', '04/12/1996', '21/09/1996', '28/06/1996', '06/07/1996'],
    'HAD_A_MASSAGE': [0, 1, 1, 1, 0],
    'BROUGHT_A_FRIEND': [1, 0, 0, 0, 1]
}

df = pd.DataFrame(data)

# 转换日期列(注意你的日期格式是DD/MM/YYYY)
df['ARRIVED'] = pd.to_datetime(df['ARRIVED'], format='%d/%m/%Y')
df['LEFT'] = pd.to_datetime(df['LEFT'], format='%d/%m/%Y')

# 按ID和就诊日期排序,保证每个患者的记录是时间顺序
df = df.sort_values(['ID', 'ARRIVED']).reset_index(drop=True)

第二步:向量化统计再入院次数

方案1:分组广播运算(推荐,性能最优)

这个方法利用NumPy的广播机制,对每个患者的所有就诊记录做批量时间差计算,完全避免循环:

def count_readmissions(group):
    # 将出院日期转成列向量,入院日期转成行向量,做广播计算时间差
    left_dates = group['LEFT'].values.reshape(-1, 1)
    arrived_dates = group['ARRIVED'].values
    
    # 筛选:后续入院日期必须在当前出院日期之后,且间隔≤30天
    time_diff = arrived_dates - left_dates
    valid_readmissions = (time_diff > pd.Timedelta(0)) & (time_diff <= pd.Timedelta(days=30))
    
    # 统计每行符合条件的次数
    return valid_readmissions.sum(axis=1)

# 分组应用函数,得到每个就诊的30天再入院次数
df['30DAY_READMISSION_COUNT'] = df.groupby('ID', group_keys=False).apply(count_readmissions)

方案2:IntervalIndex 区间匹配

利用Pandas的IntervalIndex快速匹配落在30天窗口内的入院记录,逻辑更直观:

def count_readmissions_interval(group):
    # 为每个出院日期创建[LEFT, LEFT+30天)的时间区间
    intervals = pd.IntervalIndex.from_arrays(
        group['LEFT'], 
        group['LEFT'] + pd.Timedelta(days=30), 
        closed='left'  # 包含出院当天,排除30天后的日期
    )
    
    # 统计每个入院日期落在哪些区间里,然后按区间求和
    return intervals.get_indexer(group['ARRIVED']).reshape(-1, len(intervals)).sum(axis=0)

df['30DAY_READMISSION_COUNT'] = df.groupby('ID', group_keys=False).apply(count_readmissions_interval)

为什么rolling.apply效果不好?

df.rolling().apply本质上是逐窗口循环执行自定义函数,没有利用Pandas/NumPy的向量化优化,当数据量较大时,性能会急剧下降。而上面的两种方案都是基于底层的向量化运算,能把性能提升几倍甚至几十倍。

结果验证

运行上面的代码后,你的DataFrame会新增30DAY_READMISSION_COUNT列,对应每个就诊记录的30天内再入院次数:

  • ID=3的第一次就诊(LEFT=1996-06-28),后续6天就有一次入院,所以计数为1
  • ID=1的两次就诊间隔超过30天,所以第一次计数为0,第二次没有后续就诊,计数为0

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:35:44