Scala:collect_list() 在 Window 上保持空值

Who*_*AmI 2 scala apache-spark partition-by apache-spark-sql

我有一个如下所示的数据框:

+----+----+----+
|colA|colB|colC|
+----+----+----+
|1   |1   |23  |
|1   |2   |63  |
|1   |3   |null|
|1   |4   |32  |
|2   |2   |56  |
+----+----+----+
Run Code Online (Sandbox Code Playgroud)

我应用以下说明,以便在 C 列中创建一系列值:

import org.apache.spark.sql.functions._
import org.apache.spark.sql.expressions._
df.withColumn("colD", 
collect_list("colC").over(Window.partitionBy("colA").orderBy("colB")))
Run Code Online (Sandbox Code Playgroud)

结果是这样的,即创建列 D 并在删除null值时将列 C 的值包含为一个序列:

+----+----+----+------------+
|colA|colB|colC|colD        |
+----+----+----+------------+
|1   |1   |23  |[23]        |
|1   |2   |63  |[23, 63]    |
|1   |3   |null|[23, 63]    |
|1   |4   |32  |[23,63,32]  |
|2   |2   |56  |[56]        |
+----+----+----+------------+
Run Code Online (Sandbox Code Playgroud)

但是,我想在新列中保留空值并得到以下结果:

+----+----+----+-----------------+
|colA|colB|colC|colD             |
+----+----+----+-----------------+
|1   |1   |23  |[23]             |
|1   |2   |63  |[23, 63]         |
|1   |3   |null|[23, 63, null]   |
|1   |4   |32  |[23,63,null, 32] |
|2   |2   |56  |[56]             |
+----+----+----+-----------------+
Run Code Online (Sandbox Code Playgroud)

如您所见null,结果中仍然有值。你知道我该怎么做吗?

mar*_*oss 5

正如 LeoC 提到的,collect_list将删除空值。这种行为似乎有一种解决方法。通过将每个标量包装到数组collect_list中,[[23], [63], [], [32]]然后将导致当你这样做flatten时你会得到[23, 63,, 32]. 数组中的那些缺失值是空值。

collect_listflatten内置SQL函数我相信是在介绍了星火2.4。我没有研究实现来验证这是预期的行为,所以我不知道这个解决方案有多可靠。

import org.apache.spark.sql.functions._
import org.apache.spark.sql.expressions._

val df = Seq(
  (Some(1), Some(1), Some(23)),
  (Some(1), Some(2), Some(63)),
  (Some(1), Some(3), None),
  (Some(1), Some(4), Some(32)),
  (Some(2), Some(2), Some(56))
).toDF("colA", "colB", "colC")

val newDf = df.withColumn("colD", flatten(collect_list(array("colC"))
    .over(Window.partitionBy("colA").orderBy("colB"))))


+----+----+----+-------------+
|colA|colB|colC|         colD|
+----+----+----+-------------+
|   1|   1|  23|         [23]|
|   1|   2|  63|     [23, 63]|
|   1|   3|null|    [23, 63,]|
|   1|   4|  32|[23, 63,, 32]|
|   2|   2|  56|         [56]|
+----+----+----+-------------+
Run Code Online (Sandbox Code Playgroud)