Scala 迭代数组[DateType]类型的Spark列,查看数组中是否有连续两天

Scala 迭代数组[DateType]类型的Spark列,查看数组中是否有连续两天,scala,apache-spark,apache-spark-sql,Scala,Apache Spark,Apache Spark Sql,我有一个DataFrame,它由两列组成。第一个是ID,第二个是与该ID关联的多个日期的数组 我需要遍历包含日期的列,看看该数组中是否有连续的两天 +--------------------+--------------------+ | id| date| +--------------------+--------------------+ |1003 |[2018-02-12, 2018...|

我有一个DataFrame,它由两列组成。第一个是
ID
,第二个是与该
ID
关联的多个日期的数组

我需要遍历包含日期的列,看看该数组中是否有连续的两天

+--------------------+--------------------+
|                  id|                date|
+--------------------+--------------------+
|1003                |[2018-02-12, 2018...|
|1003                |[2018-02-04, 2018...|
|1003                |[2018-02-05, 2018...|
|1003                |[2018-02-02, 2018...|
|1003                |[2018-02-28, 2018...|
|1003                |[2018-02-07, 2018...|
|1003                |[2018-02-13, 2018...|
|1003                |[2018-02-21, 2018...|
|1003                |[2018-02-15, 2018...|
|1003                |[2018-02-15, 2018...|
+--------------------+--------------------+

如果您使用的是Spark>=2.4,则可以在阵列上使用。以下是一个例子:

// example data
val df = Seq(
(1003, Array("2019-01-13", "2019-01-14", "2019-05-O3")), 
(1004, Array("2019-02-23", "2019-01-18", "2019-12-O6")), 
(1005, Array("2019-03-10", "2019-06-23", "2019-06-24")), 
(1006, Array("2019-04-11", "2019-04-18", "2019-14-19"))
).toDF("id","date")

// first we sort the dates in the array column
val sortedDatesDf = df.select(col("id"), array_sort(col("date")).alias("dates"))

// we apply transform, and exists function on the sorted array of dates
sortedDatesDf.withColumn("consecutive_dates", exists(transform(col("dates"), 
(x, i) => lit(date_add(x, lit(1)) === col("dates")(i+1))), x => x)
).show()
输出:

+----+------------------------------------+-----------------+
|id  |dates                               |consecutive_dates|
+----+------------------------------------+-----------------+
|1003|[2019-01-13, 2019-01-14, 2019-05-O3]|true             |
|1004|[2019-01-18, 2019-02-23, 2019-12-O6]|null             |
|1005|[2019-03-10, 2019-06-23, 2019-06-24]|true             |
|1006|[2019-04-11, 2019-04-18, 2019-14-19]|null             |
+----+------------------------------------+-----------------+
它是如何工作的?

  • 首先,我们对日期数组进行排序,以便比较两个连续的值。
    array\u sort
    函数将按升序对输入数组进行排序
  • transform
    函数采用排序数组和lambda函数:
    (x,i)=>布尔值
    。其中
    x
    实际值和
    i
    其在数组中的索引。因此,为了知道两个日期是否连续,我们将一天添加到
    x
    ,并检查它是否等于数组中的下一个日期(索引
    i+1
  • 最后,我们使用
    exists
    函数和lambda函数
    x=>Boolean
    检查转换数组中是否至少有一个值
    true
    ,因为这些值是Boolean类型的,所以我们只需要
    x=>x
如何在没有高阶函数的情况下执行此操作?

如果您不能使用上述解决方案,您可以使用以下其他解决方案:

  • 创建一个UDF函数,该函数接受日期列表,如果它包含两个连续日期,则返回布尔值,然后将其与DF一起使用:
    DF。withColumn(“连续的_日期”,包含连续的日期(col(“日期”))
  • 另一种解决方案是分解
    日期
    列,然后使用一些SQL窗口函数(
    滞后
    行数
    ,…)来检测具有连续日期的ID,最后,按ID进行分组

Hi@tatevik,看看
lag
和窗口功能,这就是您所需要的