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

遍历ID列表统计手术块数:寻求高效替代双for循环方案

嘿,我懂你不想用低效的两层for循环来统计手术块的心情——Pandas其实有一套非常高效的向量化操作方案,完全能搞定这个需求,而且代码简洁速度还快!

先明确下需求:我们要给每个患者统计连续手术('o')的块数,比如患者1的手术记录是2015-06-03、2015-07-01(这是一个块),然后2016-03-16、2016-04-13(第二个块),所以总共是2个手术块,对吧?

下面是具体的实现步骤,我会一步步解释:

第一步:准备数据(还原你的示例DataFrame)

首先我们先把你给出的示例数据转换成标准的Pandas DataFrame,确保格式正确:

import pandas as pd

data = [
    ['1,l', '2015-03-30', 'c'],
    ['1,l', '2015-06-03', 'o'],
    ['1,l', '2015-07-01', 'o'],
    ['1,l', '2015-07-20', 'c'],
    ['1,l', '2016-03-16', 'o'],
    ['1,l', '2016-04-13', 'o'],
    ['1,l', '2016-05-09', 'c'],
    ['2,l', '2014-12-23', 'c'],
    ['2,l', '2015-01-21', 'o'],
    ['2,l', '2015-03-16', 'c'],
    ['2,l', '2015-11-23', 'o'],
]

AllPat = pd.DataFrame(data, columns=['Pat', 'Date', 'Visit'])
# 把Date列转换成日期类型,确保后续排序和判断的准确性
AllPat['Date'] = pd.to_datetime(AllPat['Date'])

第二步:核心逻辑实现

我们可以利用Pandas的groupby、shift和cumsum来高效计算手术块:

# 1. 先按患者ID和就诊日期排序,保证就诊顺序严格按时间先后
AllPat_sorted = AllPat.sort_values(['Pat', 'Date'])

# 2. 标记当前行是否为手术记录
AllPat_sorted['is_operation'] = AllPat_sorted['Visit'] == 'o'

# 3. 对每个患者,判断当前行是否是一个新手术块的起始:
#    规则是:当前是手术,且上一行不是手术;或者是该患者的第一条记录且是手术
AllPat_sorted['block_start'] = AllPat_sorted.groupby('Pat')['is_operation'].apply(
    lambda x: x & ~x.shift(fill_value=False)
)

# 4. 按患者分组求和,得到每个患者的手术块总数
operation_blocks = AllPat_sorted.groupby('Pat')['block_start'].sum().reset_index()
operation_blocks.columns = ['Pat', 'Operation_Blocks']

运行这段代码后,operation_blocks的结果完全符合预期:

PatOperation_Blocks
1,l2
2,l2

为什么这个方法比两层循环高效?

  • 这里用的都是Pandas的向量化操作,底层是用C实现的,比Python层面的循环快得多——尤其是当你的DataFrame有几万甚至几十万行的时候,性能差距会非常明显。
  • 代码逻辑清晰,每一步都有明确的意义,也更容易维护和调试。

额外小提示

如果你的原始数据已经是按患者和日期排序好的,那第一步的sort_values可以省略,但为了代码的鲁棒性,我还是建议加上,避免因为数据顺序混乱导致结果错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:11:14