如何在 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,]|
+------------+
以下代码将在 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|
+---------+----+----+----+
我能做的最好的事情就是在嵌套数组中实现我想要的效果。
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 为我接下来想做的事情工作。
我有具体的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,]|
+------------+
以下代码将在 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|
+---------+----+----+----+
我能做的最好的事情就是在嵌套数组中实现我想要的效果。
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 为我接下来想做的事情工作。