如何在 Spark Java 中将数组分解为多列

How to explode an array into multiple columns in Spark Java

我有具体的Dataframe

+-------+----------------------+
|BlockId|Entity_BlockNumberList|
+-------+----------------------+
|      1|      [[1, 4], [3, 5]]|
|      2|      [[1, 4], [3, 5]]|
|      3|      [[2, 4], [4, 4]]|
|      4|      [[2, 4], [4, 4]]|
|      5|      [[2, 4], [3, 5]]|
|      6|      [[3, 5], [5, 3]]|
|      7|      [[1, 4], [4, 4]]|
|      8|  [[3, 5], [4, 4], ...|
|      9|  [[1, 4], [2, 4], ...|
+-------+----------------------+

我想为第 2 列中嵌套数组的每个元素创建多列 类似的东西

BlockId | Entity_BlockNumberList | 1st Array | 2nd Array | ...

类似于 explode 但在列中使用 Javadoc 我在网上找到了这段代码

val numCols = df
  .withColumn("letters_size", size($"letters"))
  .agg(max($"letters_size"))
  .head()
  .getInt(0)

df
  .select(
    (0 until numCols).map(i => $"letters".getItem(i).as(s"col$i")): _*
  )
  .show()

它在 Scala 中,但我不太明白如何使用 Java.

来执行 select 函数,尤其是(0 直到 numCols)

示例: 输入:

+---------+
|  letters|
+---------+
|[a, b, c]|
|[d, e, f]|
|     null|
+---------+

预期输出:

+----+----+----+
|col0|col1|col2|
+----+----+----+
|   a|   b|   c|
|   d|   e|   f|
|null|null|null|
+----+----+----+

但不是硬编码,因为我的数组长度不同。

我试过了

df.selectExpr(df.select(
                expr("concat('struct(',concat_ws(',',transform(sequence(0,max(size(entities))-1),x -> concat('entities[',x,'] as col',x))),') as columns')")
                ).as(Encoders.STRING()).head()).show();

输出如下:

+------------+
|     columns|
+------------+
|    [1, 3,,]|
|    [1, 3,,]|
|    [2, 4,,]|
|    [2, 4,,]|
|    [2, 3,,]|
|    [3, 5,,]|
|    [1, 4,,]|
|[3, 4, 5, 6]|
|  [1, 2, 5,]|
+------------+

以下代码将在 scalajava

中运行
df.show(false)
+---------+
|letters  |
+---------+
|[a, b, c]|
|[d, e, f]|
|[]       |
+---------+
val colExpr = df.select(
        expr("concat('struct(',concat_ws(',',transform(sequence(0,max(size(letters))-1),x -> concat('letters[',x,'] as col',x))),') as columns')")
    )
    .as[String]
    .head

colExpr 值将是 struct(letters[0] as col0,letters[1] as col1,letters[2] as col2) as columns.

你可以直接在df.selectExpr(colExpr)中使用这个,也可以像下面这样使用。


df
.withColumn("columns",expr(colExpr))
.select($"letters",$"columns.*")
.show(false)

+---------+----+----+----+
|letters  |col0|col1|col2|
+---------+----+----+----+
|[a, b, c]|a   |b   |c   |
|[d, e, f]|d   |e   |f   |
|[]       |null|null|null|
+---------+----+----+----+

我能做的最好的事情就是在嵌套数组中实现我想要的效果。

for (int i; i < numCols; i++) {
    df = df.withColumn("c" + i, df.col("entities").getItem(i));
}

输出:

+-----+------------+---+---+----+----+
|block|    entities| c0| c1|  c2|  c3|
+-----+------------+---+---+----+----+
|    1|      [1, 3]|  1|  3|null|null|
|    2|      [1, 3]|  1|  3|null|null|
|    3|      [2, 4]|  2|  4|null|null|
|    4|      [2, 4]|  2|  4|null|null|
|    5|      [2, 3]|  2|  3|null|null|
|    6|      [3, 5]|  3|  5|null|null|
|    7|      [1, 4]|  1|  4|null|null|
|    8|[3, 4, 5, 6]|  3|  4|   5|   6|
|    9|   [1, 2, 5]|  1|  2|   5|null|
+-----+------------+---+---+----+----+

Kinda 为我接下来想做的事情工作。