出于类似的需要,我指的是How to explode an array into multiple columns in Spark。
我可以对单个数组字段数据框使用该代码,但是,当我有多个数组字段数据框时,无法将它们都转换为多列。
例如,
dataframe1
+--------------------+----------------------------------+----------------------------------+
| f1 |f2 |f3 |
+--------------------+----------------------------------+----------------------------------+
|12 | null| null|
|13 | null| null|
|14 | null| null|
|15 | null| null|
|16 | null| null|
|17 | [[Hi, 256, Hello]]| [[a, b], [a, b, c],[a, b]]|
|18 | null| null|
|19 | null| null|
+--------------------+----------------------------------+----------------------------------+
我想将其转换为以下数据框:
dataframe2
+--------------------+----------------------------------+----------------------------------+----------------------------------+
| f1 |f2_0 |f3_0 |f3_1 |
+--------------------+----------------------------------+----------------------------------+----------------------------------+
|12 | null| null| null|
|13 | null| null| null|
|14 | null| null| null|
|15 | null| null| null|
|16 | null| null| null|
|17 | [Hi, 256, Hello]| [a, b]| [a, b, c]|
|18 | null| null| null|
|19 | null| null| null|
+--------------------+----------------------------------+----------------------------------+----------------------------------+
我尝试使用以下代码:
val dataframe2 = dataframe1.select(
col("f1") +: (0 until 2).map(i => col("f2")(i).alias(s"f2_$i")): _* +: (0 until 2).map(i => col("f3")(i).alias(s"f3_$i")): _*
)
但是在第一个“ _ *”之后期望“)”时抛出了错误。
答案 0 :(得分:1)
+:
在Scala中用于将单个元素添加到列表中。它不能用于将两个列表连接在一起。相反,您可以按以下方式使用++
:
val cols = Seq(col("f1"))
++ (0 until 1).map(i => col("f2")(i).alias(s"f2_$i"))
++ (0 until 2).map(i => col("f3")(i).alias(s"f3_$i"))
val dataframe2 = dataframe1.select(cols: _*)
请注意,要使用此方法,您需要事先知道列表中的元素数量。上面,我将f2
列的2更改为1。
答案 1 :(得分:0)
Shaido答案已经是正确的,并且此答案只是对此的增强。在这里,我只是添加了动态查找列的最大长度。
如果列f2
和f3
已经是数组,则按以下方法计算相应的最大数组大小。
val s1 = df.select(max(size(df("f2")))).first().getInt(0)
val s2 = df.select(max(size(df("f3")))).first().getInt(0)
否则,如果应基于定界符将列拆分并进一步划分为列,请首先按以下方式计算大小。
val s1 = df.select(max(size(split(df("f2"), ",")))).first().getInt(0)
val s2 = df.select(max(size(split(df("f3"), ",")))).first().getInt(0)
然后我们可以在Shaido答案的map函数中使用s1
,s2
(0 until s1).map( .....