Python 如何将此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

我有一个包含患者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 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值并对其进行过滤-这更简单、更直接。