按事件前后分组行序列:基于DataFrame提取c-i-c检查注射序列
提取DataFrame中的「检查-注射-检查(c-i-c)」序列集合
我来帮你搞定这个提取c-i-c序列的问题!针对你给出的患者检查和注射数据,咱们可以用Pandas一步步实现需求,而且完全支持将前一个序列的后置检查作为下一个序列的前置检查。
步骤1:准备数据并格式化
首先咱们把原始数据转换成标准的Pandas DataFrame,同时确保日期列是datetime格式,方便后续排序:
import pandas as pd # 原始数据 raw_data = [ ["1,d", "2016-01-25", 122, "c"], ["1,d", "2016-04-26", 213, "i"], ["1,d", "2016-05-23", 274, "c"], ["1,d", "2016-08-31", 201, "c"], ["1,d", "2016-10-25", 223, "i"], ["3,s", "2015-05-26", 123, "c"], ["3,s", "2015-07-01", 450, "i"], ["3,s", "2015-07-21", 234, "c"], ["3,s", "2016-01-13", 345, "i"], ["3,s", "2016-02-22", 278, "c"], ] # 转换为DataFrame并处理日期 df = pd.DataFrame(raw_data, columns=["Pat", "Date", "ID", "Visit"]) df["Date"] = pd.to_datetime(df["Date"])
步骤2:按患者分组并排序
因为序列是按时间顺序生成的,所以必须先按患者分组,再对每组内的事件按日期升序排列:
# 分组并排序,确保每个患者的事件按时间先后排列 sorted_df = df.groupby("Pat", group_keys=False).apply(lambda x: x.sort_values("Date")).reset_index(drop=True)
步骤3:定位符合条件的c-i-c序列
咱们可以通过移位操作快速找到每个事件的前后事件,然后筛选出中间是注射(i)、前后都是检查(c)的节点——这些节点就是c-i-c序列的核心,再提取对应的前后检查事件即可:
# 为每个事件添加前一个和后一个Visit类型的列 sorted_df["prev_visit"] = sorted_df.groupby("Pat")["Visit"].shift(1) sorted_df["next_visit"] = sorted_df.groupby("Pat")["Visit"].shift(-1) # 筛选出符合c-i-c结构的中间注射事件 valid_injections = sorted_df[(sorted_df["Visit"] == "i") & (sorted_df["prev_visit"] == "c") & (sorted_df["next_visit"] == "c")] # 提取完整的c-i-c序列 sequence_list = [] for idx, injection_row in valid_injections.iterrows(): patient = injection_row["Pat"] # 生成唯一的序列ID seq_id = f"{patient}_seq_{len(sequence_list)+1}" # 提取前置检查、注射、后置检查的行数据 pre_check = sorted_df.loc[idx-1].to_dict() injection = injection_row.to_dict() post_check = sorted_df.loc[idx+1].to_dict() # 为每个事件添加序列ID和角色标记 sequence_list.append({**pre_check, "Seq_ID": seq_id, "Seq_Role": "前置检查"}) sequence_list.append({**injection, "Seq_ID": seq_id, "Seq_Role": "注射"}) sequence_list.append({**post_check, "Seq_ID": seq_id, "Seq_Role": "后置检查"}) # 转换为结果DataFrame并调整列顺序 result_df = pd.DataFrame(sequence_list) result_df = result_df[["Seq_ID", "Pat", "Date", "ID", "Visit", "Seq_Role"]]
最终结果
运行上述代码后,result_df就包含了所有符合要求的c-i-c序列:
Seq_ID Pat Date ID Visit Seq_Role 0 1,d_seq_1 1,d 2016-01-25 122 c 前置检查 1 1,d_seq_1 1,d 2016-04-26 213 i 注射 2 1,d_seq_1 1,d 2016-05-23 274 c 后置检查 3 3,s_seq_1 3,s 2015-05-26 123 c 前置检查 4 3,s_seq_1 3,s 2015-07-01 450 i 注射 5 3,s_seq_1 3,s 2015-07-21 234 c 后置检查 6 3,s_seq_2 3,s 2015-07-21 234 c 前置检查 7 3,s_seq_2 3,s 2016-01-13 345 i 注射 8 3,s_seq_2 3,s 2016-02-22 278 c 后置检查
可以看到,患者3,s的第二个序列复用了第一个序列的后置检查作为前置检查,完美符合你的需求!
内容的提问来源于stack exchange,提问作者AO_30
相关产品推荐
相关产品推荐

