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

如何按自定义时长窗口分组统计Pandas DataFrame患者就诊数

解决方案

以下是实现需求的函数代码,包含两种实现方式(直观版和高效版):

直观实现(适合小数据集)

import pandas as pd

def group_by_duration(df, x, y):
    # 获取数据中的最小和最大日期(仅日期部分)
    min_date = df['demandTime'].dt.date.min()
    max_date = df['demandTime'].dt.date.max()
    
    # 生成所有窗口的起始时间:从min_date的x时开始,到max_date的x时,每天一个
    window_starts = pd.date_range(
        start=f"{min_date} {x}:00:00",
        end=f"{max_date} {x}:00:00",
        freq='D'
    )
    
    # 构造窗口的起始和结束时间DataFrame
    windows = pd.DataFrame({
        'start': window_starts,
        'end': window_starts + pd.Timedelta(hours=y)
    })
    
    # 统计每个窗口内的患者数量
    windows['total_patient'] = windows.apply(
        lambda row: df[
            (df['demandTime'] >= row['start']) & 
            (df['demandTime'] < row['end'])
        ]['patientVisit_id'].count(),
        axis=1
    )
    
    # 整理输出格式:提取起始日期作为ds列,保留患者数
    output_df = pd.DataFrame({
        'ds': windows['start'].dt.date,
        'total_patient': windows['total_patient']
    })
    
    return output_df

高效向量化实现(适合大数据集)

如果数据集较大,apply循环效率较低,可以使用IntervalIndex和pd.cut实现向量化统计:

import pandas as pd

def group_by_duration(df, x, y):
    min_date = df['demandTime'].dt.date.min()
    max_date = df['demandTime'].dt.date.max()
    
    window_starts = pd.date_range(
        start=f"{min_date} {x}:00:00",
        end=f"{max_date} {x}:00:00",
        freq='D'
    )
    window_ends = window_starts + pd.Timedelta(hours=y)
    
    # 创建区间索引,左闭右开(匹配需求中的时间范围)
    intervals = pd.IntervalIndex.from_arrays(window_starts, window_ends, closed='left')
    
    # 将每个demandTime分配到对应的区间,统计数量
    count_series = pd.cut(df['demandTime'], bins=intervals).value_counts()
    # 确保所有窗口都被包含,缺失的窗口填充0
    count_series = count_series.reindex(intervals, fill_value=0)
    
    # 整理输出
    output_df = pd.DataFrame({
        'ds': window_starts.dt.date,
        'total_patient': count_series.values
    })
    
    return output_df

测试验证

使用你提供的示例数据测试:

df = pd.DataFrame({
    "patientVisit_id": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
    "demandTime": pd.to_datetime([
        "2023-06-06 06:00:00", "2023-06-06 07:00:00", "2023-06-06 08:00:00",
        "2023-06-06 09:00:00", "2023-06-06 10:00:00", "2023-06-07 02:00:00",
        "2023-06-07 12:00:00", "2023-06-07 13:00:00", "2023-06-07 14:00:00"
    ])
})

result = group_by_duration(df, x=6, y=22)
print(result)

输出结果与你的示例完全一致:

ds  total_patient
0  2023-06-06              6
1  2023-06-07              3

关键逻辑说明

  1. 窗口生成:从数据的最小日期的X时开始,到最大日期的X时结束,每天生成一个窗口起始点,确保覆盖所有需要统计的时间范围。
  2. 时间范围判断:每个窗口的时间范围是[start, start+Y小时),左闭右开的逻辑避免了时间点重复统计(比如刚好落在窗口结束时间的记录不会被计入当前窗口)。
  3. 统计逻辑:根据patientVisit_id的记录数统计患者数量(因为每个ID对应一条就诊记录,用count()即可;如果存在重复ID,可改用nunique()统计唯一患者数)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 19:10:13