我有一个非常大的数据框(> 5GB),其中包含以下信息的行:
PatientID StudyDate Modality SliceNo Filename
每行包含3D医学图像中的一个切片,对于模态,我有PET
和CT
,它们是两种不同类型的医学扫描。例如,我可以拥有:
PatientID StudyDate Modality SliceNo Filename
000000001 2017-08-01 PT 0 XXXXX
000000001 2017-08-01 PT 1 XXXXX
...
000000001 2017-08-01 PT 100 XXXXX
000000001 2017-04-01 PT 0 XXXXX
000000001 2017-04-01 PT 1 XXXXX
...
000000001 2016-08-01 CT 0 XXXXX
000000001 2016-08-01 CT 1 XXXXX
...
000000001 2016-08-01 CT 100 XXXXX
000000001 2017-04-15 CT 0 XXXXX
000000001 2017-04-15 CT 1 XXXXX
...
000000001 2017-04-15 CT 100 XXXXX
...
000000002 2016-07-01 PT 0 XXXXX
000000002 2016-07-01 PT 1 XXXXX
...
000000002 2016-07-01 PT 100 XXXXX
000000002 2015-07-21 PT 0 XXXXX
000000002 2015-07-21 PT 1 XXXXX
...
000000002 2015-07-21 PT 100 XXXXX
000000002 2014-07-01 PT 0 XXXXX
000000002 2014-07-01 PT 1 XXXXX
...
000000002 2014-07-01 PT 100 XXXXX
000000002 2015-08-05 CT 0 XXXXX
000000002 2015-08-05 CT 1 XXXXX
...
000000002 2015-08-05 CT 100 XXXXX
现在,我想找到与PT
扫描相对应的每位患者CT
,如果在进行CT
扫描之前不到一个月,则定义对应关系。其他扫描可以取消(删除)。通常,可能会有多个CT扫描和多个PT扫描,但是每个CT都应关联一个扫描。例如,如果CT扫描日期为2017-04-01,则在2017-03-01和2017-04-01之间的所有PT扫描都符合条件。
选择满足条件的PT扫描的有效方法是什么:对于该患者,最晚一个月再进行一次CT扫描?
以该示例为例,患者000000001
的2016年8月1日的CT将没有相关的PT扫描(可以),但是由于CT的原因,将选择2017年4月1日的PT扫描PT扫描后最多31天进行了2017-04-15扫描。因此,在这种情况下,2017-08-01的PT扫描被过滤掉了。应过滤所有处于这种情况的切片(SliceNo
)(每次扫描可以有不同数量的切片)。对于患者000000002
,仅保留2015-07-21的PT扫描。
答案 0 :(得分:1)
以下算法不能涵盖所有情况,但我希望它能对您有所帮助。
首先,我们忽略了一些列,因为实际上我们只对cols = ['PatientID', 'StudyDate', 'Modality']
感兴趣。所以我们写
df = df[cols].sort_values(cols).drop_duplicates()
现在,我们确定CT
和PT
期间:
df['Modality_'] = df.groupby(['PatientID'])['Modality'].shift(1).fillna(method='bfill')
df['Group'] = (1-df['Modality_'].eq(df['Modality'])).cumsum()
接下来,我们计算每个期间的最大和最小日期
agg = df.pivot_table(index=['PatientID', 'Group'], columns=['Modality'], values=['StudyDate'], aggfunc=['max', 'min'])
最后,我们提取PT
和CT
数据。由于PT
期间之后总是有CT
期间,因此我们可以将前一个组向后移动一个并直接进行比较
pt = agg.loc[:, ('max', 'StudyDate', 'PT')].groupby(['PatientID']).shift(1)
ct = agg.loc[:, ('min', 'StudyDate', 'CT')]
我们要选择偏移量少于30天的日期:
ok = ct - pt < pd.offsets.Day(30)
ok = ok[ok == True].to_frame()
现在我们完成了:
print(ok.join(ct.to_frame()))
0 (max, StudyDate, CT)
PatientID Group
1 2 True 2017-04-15
2 4 True 2015-08-05
print(ok.join(pt.to_frame()))
0 (max, StudyDate, PT)
PatientID Group
1 2 True 2017-04-01
2 4 True 2015-07-21