如何在spark java中将数组分解为多列

7fhtutme  于 2021-05-17  发布在  Spark
关注(0)|答案(2)|浏览(503)

我有特定的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], ...|
+-------+----------------------+

我想为第二列中嵌套数组的每个元素创建多个列

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,]|
+------------+
ztmd8pv5

ztmd8pv51#

为了实现我想要的在嵌套数组中工作的目标,我所能做的最好的事情就是这样做。

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|
+-----+------------+---+---+----+----+

有点像我下一步想做的。

waxmsbnn

waxmsbnn2#

下面的代码将在 scala 还有 java ```
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|
+---------+----+----+----+

相关问题