我尝试过的每种方法都会给我留下整列的总和。每行都有一个由双精度填充的数组。我需要的是每一行的求和列。
因此,您首先使用如下所示的数据框:
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
来获取每个数组的最大值而不是求和,并且返回整个列的最大值。因此,可能是我不了解的一些基本语法问题。
预先感谢您的帮助。
答案 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]。