Эффективный поиск строк в течение 31 дня после других строк - PullRequest
1 голос
/ 21 апреля 2019

У меня очень большой фрейм данных (> 5 ГБ), в котором есть строки со следующей информацией:

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.Другие сканы могут быть отклонены.В общем случае может быть несколько сканирований КТ и несколько сканирований ПТ, но с каждым КТ должен быть связан один скан.Например, если датой компьютерного томографа будет 2017-04-01, то будут выполнены все сканирования PT между 2017-03-01 и 2017-04-01.

Какой эффективный способ выбрать эти PTсканы, которые удовлетворяют условию: для этого пациента есть КТ, самое большее на один месяц позже?

Например, и у пациента 000000001 КТ 2016-08-01 не будет иметь ассоциированного PTсканировать (что нормально), но будет выбрано сканирование PT 2017-04-01, так как сканирование CT 2017-04-15 было выполнено максимум через 31 день после сканирования PT.Таким образом, в этом случае сканирование PT 2017-08-01 отфильтровывается.Все срезы (SliceNo) (может быть разное количество срезов на сканирование) с этим условием должны быть отфильтрованы.Для пациента 000000002 сохраняется только ПТ скан 2015-07-21.

1 Ответ

1 голос
/ 23 апреля 2019

Следующий алгоритм не охватывает все случаи, но я надеюсь, что он тоже поможет.

Сначала мы игнорируем некоторые столбцы, потому что на самом деле нас интересует только 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...