我有DF,其中包括患者ID和患者接受医疗程序的日期。我需要过滤DF,以仅包括至少接受过两次手术的患者,两次手术间隔30到365天。我只需要保留患者ID和符合时间范围标准的第一次手术。
原始DF:
| 患者ID|日期|
| --|--|
| 一|18年3月1日|
| 一|18年3月15日|
| B| 19年4月1日|
| B| 19年4月4日|
| B| 19年4月7日|
| B| 19年6月3日|
和滤波后的DF:
| 患者ID|日期|
| --|--|
| B| 19年4月7日|
这是我试过的代码.
w=Window.partitionBy("Pat_ID").orderBy(col("date"))
for i in range(1, 366):
df = df.withColumn(f"daysbetween_{i}", when ((datediff((F.lead(F.col('dx_date'), i).over(w)), "dx_date").between(30, 365)),1).otherwise(0))
字符串
2条答案
按热度按时间oxiaedzo1#
我这样做的总体方法是:
1.通过患者ID和range join conditions将表连接到自身
1.计算每一行的成对日期差
1.按患者ID分组,最早日期的汇总
然而,这种方法的主要问题是你可能会耗尽内存,这取决于你的数据集;因为你可能会为每个病人的
N
程序生成N^2
行。我已经添加了过滤器来只生成有效的日期对(在30-365天范围内),但是如果你的数据集真的很大,它 * 仍然有可能耗尽内存 *。以下是我的方法:
首先,模拟数据集
个字符
接下来,我创建DataFrame
filter_df
,根据最大范围筛选潜在患者。这将筛选出:我不能使用
between(30,365)
或max_range <= 365
,因为即使最大-最小范围超过365天的限制,也可能存在最小-最大对之间的差异小于365天的日期对。但是,反之则不然。如果最大-最小范围小于30天,则不能有另一个范围大于30天的日期对。
的字符串
使用inner join应用过滤器:
的字符串
然后,我通过患者id和range join conditions(基本上,将
date_diff().between()
条件添加到join(on=...)
参数) 将这个过滤后的结果与其本身连接起来。为此,我必须重命名患者id和日期列以区分它们。这为我提供了所有患者的所有有效日期对。
使用范围连接条件,我避免了生成
4^2 + 3^2 = 25
行的二次行为,而是只得到日期范围(30,365)天内的4个有效日期对。无论你使用
F.date_diff("date_b", "date_a")
还是F.date_diff("date_a", "date_b")
都没有关系--成对差分是对称的,你会得到相同的结果。负结果也没有关系,原因也是一样的。然后我按患者ID分组,并选择
min("date_a")
以获得符合此条件的 * 第一个程序 *。但是我注意到我的代码发现患者B的
1 April 2019
是答案,而不是您的示例7 April 2019
结果。根据你对“第一次”的理解,你需要修改最后一个代码块来得到你的答案。
iq0todco2#
一种使用内置Spark函数而不使用joins的方法(出于性能原因):
1.将数据按
patient_id
和collect all dates into a list分组。1.对于每个日期列表,使用this answer生成所有可能的日期对。
1.第一对的第一个日期是预产期。
字符串
测试结果:
型