我有一个df
,其中包含以下架构:
ts: TimestampType
key: int
val: int
df
按ts
的升序排序。从行(0)开始,我想在一定的时间间隔内对数据帧进行分组。
例如,如果我说df.filter(row(0).ts + expr(INTERVAL 24 HOUR)).collect()
,它应该返回行(0)的24小时时间窗口内的所有行。
有没有办法在Spark DF上下文中实现上述功能?
答案 0 :(得分:1)
一般来说,这是一项相对简单的任务。您所需要的只是UNIX时间戳上的基本算术。首先让我们将所有时间戳转换为数字:
val dfNum = df.withColumn("ts", $"timestamp".cast("long"))
接下来让我们找到所有行的最小时间戳:
val offset = dfNum.agg(min($"ts")).first.getLong(0)
并用它来计算群组:
val aDay = lit(60 * 60 * 24)
val group = (($"ts" - lit(offset)) / aDay).cast("long")
val dfWithGroups = dfNum.withColumn("group", group)
最后,您可以将其用作分组列:
dfWithGroups.groupBy($"group").agg(min($"value")).
如果您想要有意义的间隔(可解释为时间戳),只需将组乘以aDay
。
显然,这不会处理复杂的情况,例如处理夏令时或闰秒,但在大多数情况下都应该足够好。如果你需要正确处理任何一个,你使用类似的逻辑使用JUD时间和UDF。