Spark Scala - 识别多行日期之间的差距
Posted
技术标签:
【中文标题】Spark Scala - 识别多行日期之间的差距【英文标题】:Spark Scala - Identify the gap between dates across multiple rows 【发布时间】:2020-01-17 20:54:40 【问题描述】:我是 Apache Spark 的新手,我有一个用例来查找多个日期之间的日期间隔标识。
例如
在上面的示例中,成员在 2018-02-01 到 2018-02-14 之间存在间隔。如何使用 Scala 找到这个 Apache Spark 2.3.4。
上述场景的例外输出是,
【问题讨论】:
【参考方案1】:您可以使用datediff
和窗口函数lag
来检查当前行和之前行之间的日期间隔,并使用一些日期函数计算缺失的日期范围:
import org.apache.spark.sql.expressions.Window
import org.apache.spark.sql.functions._
import spark.implicits._
import java.sql.Date
val df = Seq(
(1, Date.valueOf("2018-01-01"), Date.valueOf("2018-01-31")),
(1, Date.valueOf("2018-02-16"), Date.valueOf("2018-02-28")),
(1, Date.valueOf("2018-03-01"), Date.valueOf("2018-03-31")),
(2, Date.valueOf("2018-07-01"), Date.valueOf("2018-07-31")),
(2, Date.valueOf("2018-08-16"), Date.valueOf("2018-08-31"))
).toDF("MemberId", "StartDate", "EndDate")
val win = Window.partitionBy("MemberId").orderBy("StartDate", "EndDate")
df.
withColumn("PrevEndDate", coalesce(lag($"EndDate", 1).over(win), date_sub($"StartDate", 1))).
withColumn("DayGap", datediff($"StartDate", $"PrevEndDate")).
where($"DayGap" > 1).
select($"MemberId", date_add($"PrevEndDate", 1).as("StartDateGap"), date_sub($"StartDate", 1).as("EndDateGap")).
show
// +--------+------------+----------+
// |MemberId|StartDateGap|EndDateGap|
// +--------+------------+----------+
// | 1| 2018-02-01|2018-02-15|
// | 2| 2018-08-01|2018-08-15|
// +--------+------------+----------+
【讨论】:
这个很好,但在某些日期重叠的情况下它会失败,例如如果您将(2, Date.valueOf("2018-05-01"), Date.valueOf("2018-08-05")
添加到 DF,您仍然会得到与上面相同的结果。假设已采取措施删除冗余数据,这仍然是一个很好的答案。
谢谢,但是当日期重叠时它会失败,例如如果你添加 (1,Date.valueOf("2018-01-15"),Date.valueOf("2018-01-30") ) 到 DF,您将获得 StartDateGap 为“2018-01-31”,但该成员的注册日期为“2018-01-31”。您能告诉我如何在计算之前删除重叠天数吗?
Leo,我找到了您删除重叠日期的答案之一 (***.com/questions/52877237/…)。非常感谢。我会尽力将这两者合并。如果我需要更多帮助,我会告诉你。非常感谢。
@Gowri24,是的,上述解决方案基于您的简单示例数据,没有重叠日期范围。将我的其他解决方案与此解决方案相结合将起作用。应用其他解决方案后,只需将 win3
定义为 Window.partitionBy("MemberId", "StartDate", "EndDate").orderBy("StartDate", "EndDate")
应用到生成的 DataFrame resDF.withColumn("RowNum", row_number.over(win3)).where($"RowNum" === 1)
,然后应用上述转换来查找差距。
@LeoC,感谢您的回复。以上是关于Spark Scala - 识别多行日期之间的差距的主要内容,如果未能解决你的问题,请参考以下文章
如何合并来自多行的值,以便它们可以一起处理 - Spark scala
Spark - Scala:当 json 数据分布在多行时,读取 json 文件作为数据帧不起作用?
如何在 Spark Scala 中读取带有根元素的多行 json?