如何将一列数组转换为包含Spark中每个数组的和的列?

时间:2018-06-25 02:32:01

标签: arrays scala apache-spark dataframe

我尝试过的每种方法都会给我留下整列的总和。每行都有一个由双精度填充的数组。我需要的是每一行的求和列。

因此,您首先使用如下所示的数据框:

id   c2   c3
-------------------------
1     1   [2.0, 1.0, 0.0]
2     2   [0.0, 0,0, 0.0]

因此,我想要这个:

id   c2   c3sum
-------------------------
1     1   3.0
2     2   0.0

在对“ id”执行groupBy之后,我尝试使用sum方法。我也尝试使用udf

def mySum(arr:Seq[Double]):Double=arr.reduceLeft(_+_)
val dfsum = df.withColumn("c3sum", mySum($"c3"))

udf的这些和其他变体始终返回该列中所有内容的总和。作为测试,我还尝试使用array.max来获取每个数组的最大值而不是求和,并且返回整个列的最大值。因此,可能是我不了解的一些基本语法问题。

预先感谢您的帮助。

2 个答案:

答案 0 :(得分:0)

一种可能的解决方案是使用udf(如您所试)。为了使它起作用,您需要导入并使用org.apache.spark.sql.functions.udf创建一个udf。工作示例:

import org.apache.spark.sql.functions.udf

val df = Seq(
    (1, 1, Seq(2.0, 1.0, 0.0)), 
    (2, 2, Seq(0.0, 0.0, 0.0)), 
    (3, 3, Seq(0.0, 1.0, 0.0))
).toDF("id", "c2", "c3")

val mySum = udf((arr: Seq[Double]) => arr.sum)
val dfsum = df.withColumn("c3sum", mySum($"c3"))

会给:

+---+---+---------------+-----+
| id| c2|             c3|c3Sum|
+---+---+---------------+-----+
|  1|  1|[2.0, 1.0, 0.0]|  3.0|
|  2|  2|[0.0, 0.0, 0.0]|  0.0|
|  3|  3|[0.0, 1.0, 0.0]|  1.0|
+---+---+---------------+-----+

答案 1 :(得分:0)

您可能要考虑将Dataset的{​​{1}}与map结合使用,而不是依赖于UDF:

sum

请注意,在转换为数据集之前,将import org.apache.spark.sql.functions._ val df = Seq( (1, 1, Array(2.0, 1.0, 0.0)), (2, 2, Array(0.0, 0.0, 0.0)) ).toDF("id", "c2", "c3") df. withColumn("c3", coalesce($"c3", lit(Array[Double]()))). as[(Int, Int, Array[Double])]. map{ case (id, c2, c3) => (id, c2, c3.sum) }. toDF("id", "c2", "c3sum"). show // +---+---+-----+ // | id| c2|c3sum| // +---+---+-----+ // | 1| 1| 3.0| // | 2| 2| 0.0| // +---+---+-----+ 应用于c3,以将coalesce(如果有)替换为空的Array [Double]。