Scala 如何在Spark中将两个数组字段分解为多列?

Scala 如何在Spark中将两个数组字段分解为多列?,scala,apache-spark,apache-spark-sql,Scala,Apache Spark,Apache Spark Sql,我指的是类似的需求 我可以将该代码用于单个数组字段数据帧,但是,当我有多个数组字段数据帧时,我无法将这两个字段都转换为多个列 比如说, dataframe1 +--------------------+----------------------------------+----------------------------------+ | f1 |f2 |f3

我指的是类似的需求

我可以将该代码用于单个数组字段数据帧,但是,当我有多个数组字段数据帧时,我无法将这两个字段都转换为多个列

比如说,

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")): _*
)

但是它抛出了一个错误,表示在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。

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到s1)。map(……

谢谢你的解释。我有一个语法疑问。最后一个表达式在我的代码中是什么意思?我没有从参考链接中理解该部分。@user3243499:很高兴提供帮助。我想这里的答案比我能解释的更好: