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

基于索引合并Pandas多DataFrame:保留共通患者时序数据

首先明确:你直接赋值complete["B"] = B["value2"]的方式完全不能保证值与ID正确匹配,这是按DataFrame的行索引硬塞数据,和患者ID、时序顺序无关,一旦两个DataFrame行顺序不对应,数据就会全部错位。

正确解决方案

问题根源是仅按id合并时,每个id对应多条记录,Pandas会执行笛卡尔积,导致重复。解决核心是给每个患者的时序记录添加组内序号,标记该患者的第1/2条测量值,再用id+序号作为合并键,精准匹配同患者同时序的记录。

步骤分解(以A、B为例,扩展到3个DataFrame逻辑一致):

  1. 给每个DataFrame添加组内序号
    按id分组后,为每组的行生成从1开始的序号,对应测量时序:

    import pandas as pd
    
    # 还原你的示例数据(注意你提供的df1对应B,df2对应A)
    df_A = pd.DataFrame({"id":[1,1,2,2],"value1":[80,78,76,79]})
    df_B = pd.DataFrame({"id":[2,2,3,3], "value2":[65,67,74,65]})
    
    # 添加组内时序序号
    df_A["seq"] = df_A.groupby("id").cumcount() + 1  # 从1开始计数,对应第1/2次测量
    df_B["seq"] = df_B.groupby("id").cumcount() + 1
    
  2. 筛选三个DataFrame共有的患者ID
    取所有DataFrame中ID的交集,只保留这些患者的记录:

    # 若有第三个DataFrame df_C,只需加入intersection参数即可
    common_ids = set(df_A["id"]).intersection(df_B["id"])
    
  3. 过滤数据,仅保留共同ID的记录

    df_A_filtered = df_A[df_A["id"].isin(common_ids)]
    df_B_filtered = df_B[df_B["id"].isin(common_ids)]
    
  4. 按id+seq合并数据
    此时合并不会产生笛卡尔积,精准匹配同患者同时序的记录:

    merged_df = pd.merge(df_A_filtered, df_B_filtered, on=["id", "seq"], how="inner")
    # 若有第三个DataFrame,继续执行合并:
    # merged_df = pd.merge(merged_df, df_C_filtered, on=["id", "seq"], how="inner")
    
    # 不需要seq列的话可以删除
    merged_df = merged_df.drop("seq", axis=1)
    

最终得到的结果与预期一致:

idvalue1value2
27665
27967

方法原理

每个患者的记录是按时间排序的,cumcount()生成的序号对应了该患者的第n次测量,用id+seq作为合并键,彻底避免了同患者多条记录交叉匹配的问题,完美解决笛卡尔积重复。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 20:15:42