Python 如何将此SQL代码转换为包含滞后函数的等效代码?
我有一个包含患者ID和住院时间的熊猫数据框。我想筛选出患者在前一次入院后30天内入院的行(但包括第一次入院)。使用SQL,我可以使用Python 如何将此SQL代码转换为包含滞后函数的等效代码?,python,pandas,lag,Python,Pandas,Lag,我有一个包含患者ID和住院时间的熊猫数据框。我想筛选出患者在前一次入院后30天内入院的行(但包括第一次入院)。使用SQL,我可以使用lag函数来实现这一点: case -- mark the first hospital adm when dense_rank() over (partition by adm.subject_id order by adm.admittime) = 1 then true -- mark subsequent hospital adms i
lag
函数来实现这一点:
case
-- mark the first hospital adm
when dense_rank() over (partition by adm.subject_id order by adm.admittime) = 1 then true
-- mark subsequent hospital adms if its been atleast a month since previous admission.
when round((cast(extract(epoch from adm.admittime - lag(adm.admittime, 1) over (partition by
adm.subject_id order by adm.admittime))/(60*60*24) as numeric)), 2) >= 30.0 then true
else false end as include_adm
我该如何处理熊猫呢?基本上,我想从以下数据框中筛选出一行患者ID 30:
id admit_time
0 30 2018-10-03
1 30 2018-10-29
2 13 2017-11-01
3 13 2018-02-27
id admit_time note
0 30 2018-10-03 note_content1
1 30 2018-10-03 note_content2
2 30 2018-10-29 note_content1
3 30 2018-10-29 note_content2
4 13 2017-11-01 note_content1
5 13 2018-02-27 note_content2
6 13 2018-02-27 note_content2
得到
id admit_time
0 30 2018-10-03
1 13 2017-11-01
2 13 2018-02-27
因为患者第二次入院是在首次入院后30天内。但13号患者的入院日期相差超过30天,因此这两次入院均予以保留
我上面展示的是一个示例数据帧。真正的数据帧由更多的列和行组成。更具体地说,其中一列是该患者在指定时间的临床记录。因此,除临床记录外,行中有大量重复信息。例如,上面的数据帧:
id admit_time
0 30 2018-10-03
1 30 2018-10-29
2 13 2017-11-01
3 13 2018-02-27
id admit_time note
0 30 2018-10-03 note_content1
1 30 2018-10-03 note_content2
2 30 2018-10-29 note_content1
3 30 2018-10-29 note_content2
4 13 2017-11-01 note_content1
5 13 2018-02-27 note_content2
6 13 2018-02-27 note_content2
过滤后应产生以下数据帧:
id admit_time note
0 30 2018-10-03 note_content1
1 30 2018-10-03 note_content2
2 13 2017-11-01 note_content1
3 13 2018-02-27 note_content1
4 13 2018-02-27 note_content2
试试这个:
>>将熊猫作为pd导入
>>>将numpy作为np导入
>>>df=df.sort_值(按=[“id”,“承认时间])#如果数据未排序
>>>df_2=df.join(df.groupby(“id”).min(),on=“id”,how=“left”,rsuffix=“\u min”)
>>>df_2[“time_diff”]=np.where(df_2[“id”]==df_2[“id”].shift(),(pd.to_datetime(df_2[“admit_time”])-pd.to_datetime(df_2[“admit_time”].shift()).astype('timedelta64[D]),0)
>>>df_2
承认时间我承认时间最小时间不同
0 2018-10-03 30 2018-10-03 0.0
1 2018-10-29 30 2018-10-03 26.0
2 2017-11-01 13 2017-11-01 0.0
3 2018-02-27 13 2017-11-01 118.0
>>>df_2[(df_2[“承认时间”]==df_2[“承认时间”])(df_2[“承认时间”]>=30)]
承认时间我承认时间最小时间不同
0 2018-10-03 30 2018-10-03 0.0
2 2017-11-01 13 2017-11-01 0.0
3 2018-02-27 13 2017-11-01 118.0
2注意事项:
(1) 您需要首先按id、承认时间对数据进行排序
(2) 我没有找到与densite\u rank
相等的值-因此它正在进行常规rank我们用来计算排序数据帧上每个id
组的每个入院时间的差值,并选择任何NaT
差值(即每组第一行)或差值>30天的行。最后,我们删除辅助列delta
:
df['delta'] = df.sort_values(['id', 'admit_time']).groupby('id')['admit_time'].transform(lambda x: x.diff())
df = df[df.delta.isna() | (df.delta >= pd.Timedelta(days=30))].drop(columns='delta')
输出:
id admit_time
0 30 2018-10-03
2 13 2017-11-01
3 13 2018-02-27
修订问题的更新:
按['id','note']
分组,而不仅仅是'id'
:
df['delta'] = df.sort_values(['id', 'admit_time']).groupby(['id','note'])['admit_time'].transform(lambda x: x.diff())
df = df[df.delta.isna() | (df.delta >= pd.Timedelta(days=30))].drop(columns='delta')
结果:
id admit_time note
0 30 2018-10-03 note_content1
1 30 2018-10-03 note_content2
4 13 2017-11-01 note_content1
5 13 2018-02-27 note_content1
6 13 2018-02-27 note_content2
谢谢你的回复。这是可行的,但也有一个问题。我没有指定除了一个特定列之外,几乎所有信息都相同的重复行。这将导致一次入院的时间差为零天,但这需要保留。我已经编辑了我的原始问题以包含这些额外信息。IIUC您需要按照['id','note']
分组,而不仅仅是'id'
。您的示例数据中有一个输入错误:第5行的注释应该是note_content1,而不是note_content2,不是吗?我想我已经更正了。在您的原始代码中,我添加了一个额外的OR条件,即df['delta']==pd.Timedelta(days=0)
,以及已经存在的条件,它似乎可以工作。你的想法?如果你像我现在的回答那样使用diff,你不需要这个额外的条件。这是在第一个版本中,我使用0作为第一行的时间增量。在当前代码中,我保留NaT值并对其进行过滤-这更简单、更直接。