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

Python中基于ClinicCode合并DataFrame并处理面板随时间变更问题

解决诊所Panel归属随时间变化的匹配问题

嘿,这个场景在医疗数据处理里太常见了!咱们一步步来拆解你的问题:

一、df2的格式是否适合存储随时间变化的分类信息?

答案是非常适合——只要df2的结构是清晰的「诊所代码 + 所属Panel + 变更生效日期」(最好再补充一个失效日期,或者通过后续处理生成)。

举个标准的df2结构例子:

ClinicCodePanelStartDateEndDate
APanel A2018-01-012019-12-31
APanel B2020-01-012100-01-01
BPanel X2019-01-012100-01-01

这种结构的优势在于:

  • 每条记录精准标记了某个诊所属于某个Panel的时间区间
  • 可以清晰追踪诊所Panel归属的历史变更
  • 后续匹配就诊记录时,能通过日期区间快速定位对应的Panel

如果你的df2目前只有StartDate没有EndDate也没关系,咱们可以通过代码自动生成,后面会讲具体方法。

二、如何实现就诊记录与对应Panel的匹配?

我会用Python pandas给出两种实用方案,你可以根据数据量大小选择:

先准备示例数据

首先咱们构造模拟的df1(就诊记录)和df2(Panel变更记录):

import pandas as pd

# 就诊记录df1
df1 = pd.DataFrame({
    'ClinicCode': ['A', 'A', 'B', 'C'],
    'VisitDate': pd.to_datetime(['2019-06-15', '2020-03-20', '2019-11-05', '2021-01-10']),
    'Visits': [1, 2, 1, 1]
})

# Panel变更记录df2(只有StartDate)
df2 = pd.DataFrame({
    'ClinicCode': ['A', 'A', 'B', 'C'],
    'Panel': ['Panel A', 'Panel B', 'Panel X', 'Panel Y'],
    'StartDate': pd.to_datetime(['2018-01-01', '2020-01-01', '2019-01-01', '2020-05-01'])
})

第一步:预处理df2,生成时间区间

先给df2补充EndDate,明确每个Panel归属的结束时间:

# 按诊所代码和生效日期排序,确保时间顺序正确
df2 = df2.sort_values(['ClinicCode', 'StartDate'])

# 生成EndDate:当前记录的EndDate是下一条记录的StartDate减1天
df2['EndDate'] = df2.groupby('ClinicCode')['StartDate'].shift(-1) - pd.Timedelta(days=1)

# 最后一条记录的EndDate设为未来很远的日期(比如2100年),表示当前仍生效
df2['EndDate'] = df2['EndDate'].fillna(pd.Timestamp('2100-01-01'))

方案1:用merge_asof高效匹配(推荐大数据量)

merge_asof是pandas专门用于按时间顺序匹配的函数,效率极高,适合处理十万级以上的数据:

# 先对df1按诊所代码和就诊日期排序
df1_sorted = df1.sort_values(['ClinicCode', 'VisitDate'])

# 执行时间匹配:按ClinicCode分组,匹配VisitDate >= StartDate的最近一条Panel记录
result = pd.merge_asof(
    df1_sorted,
    df2,
    left_on='VisitDate',
    right_on='StartDate',
    by='ClinicCode',
    direction='backward'  # 取不晚于VisitDate的最近一条StartDate记录
)

# 整理结果,保留需要的字段
result = result[['ClinicCode', 'VisitDate', 'Visits', 'Panel']].sort_index()

运行后你会得到符合预期的结果:

ClinicCodeVisitDateVisitsPanel
A2019-06-151Panel A
A2020-03-202Panel B
B2019-11-051Panel X
C2021-01-101Panel Y

方案2:交叉合并后筛选(适合小数据量)

如果你的数据量不大,这种方法更直观,容易理解:

# 先交叉合并两个DataFrame,把所有可能的组合列出来
merged = pd.merge(df1, df2, on='ClinicCode', how='left')

# 筛选出就诊日期落在Panel生效区间内的记录
filtered = merged[(merged['VisitDate'] >= merged['StartDate']) & (merged['VisitDate'] <= merged['EndDate'])]

# 整理结果
result = filtered[['ClinicCode', 'VisitDate', 'Visits', 'Panel']]

这个方法的结果和方案1完全一致,只是数据量大时会占用更多内存,所以优先推荐方案1。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 10:48:11