PySpark按条件获取指定时间范围内code=0对应前一行zip值的问题
问题解决方法
你现有代码不符合预期有两个核心原因:
- 未对当前行的code做过滤:不管当前行code是不是0,都会计算前序的zip值,导致code=4的行也返回了结果
- 使用
F.last时没有开启忽略空值参数:默认F.last不会跳过窗口内的null值,无法正确提取到最后一个非空的code=0对应的zip
修改后完整代码
from pyspark.sql import functions as F from pyspark.sql import Window # 先生成unix时间戳列,供窗口range计算使用 df = df.withColumn("timestamp", F.unix_timestamp("trandatetime")) # 窗口定义保持不变,按id分组,按时间戳排序,取过去24小时的前序行 w = Window.partitionBy('id').orderBy('timestamp').rangeBetween(-60*60*24, -1) # 计算逻辑修改: # 1. 只有当前行code=0时才计算取值,否则直接返回null # 2. last函数加ignorenulls=True,跳过窗口内的null值,取最近的非空zip df = df.withColumn( "Card_Present_Last_Zip", F.when( F.col("code") == '0', F.last(F.when(F.col("code") == '0', F.col("zip")), ignorenulls=True).over(w) ) )
执行后预期结果
| id | trandatetime | code | zip | timestamp | Card_Present_Last_Zip |
|---|---|---|---|---|---|
| 1 | 2020-02-06 17:33:21 | 0 | 35763 | 1581010401 | null |
| 1 | 2020-02-06 17:39:55 | 0 | 35763 | 1581010795 | 35763 |
| 1 | 2020-02-07 06:06:42 | 0 | 35741 | 1581055602 | 35763 |
| 1 | 2020-02-07 06:28:17 | 4 | 94043 | 1581056897 | null |
| 1 | 2020-02-07 07:12:13 | 0 | 35802 | 1581059533 | 35741 |
| 1 | 2020-02-07 08:23:29 | 0 | 30738 | 1581063809 | 35802 |
内容的提问来源于stack exchange,提问作者user1389739
相关产品推荐
相关产品推荐

