将列总和转换为“ val”(变量)

时间:2019-05-25 13:34:56

标签: scala apache-spark apache-spark-sql aggregation

我正在一个数据帧中执行聚合以进行百分比计算。我需要将每列的总和存储在一个单独的变量中,并且可以在除法中使用它来计算百分比

val sumOfCol1 = df.agg(round(sum("col1"),2))

此代码给出了总和,但是它将被存储为数据帧对象,并且不能用于除法。类型是:

sumOfCol1: org.apache.spark.sql.DataFrame = [round(sum(col1), 2): double]

如何将其存储为常数或双精度值,以便在以后的聚合中使用它?

2 个答案:

答案 0 :(得分:1)

要以Double的形式访问数据帧中的实际值,您需要使用collect将数据帧收集到驱动程序。该函数将返回一个包含所有行的数组,请参见documentation

由于有一个数据框,它将包含Row个对象,并且您必须使用getAs来访问实际的基础值。一种更直观的方法是先转换为数据集,然后收集:

val sumOfCol1 = df.agg(round(sum("col1"),2)).as[Double].collect()(0)

在这种情况下,由于只需要一个值,因此也可以使用first方法:

val sumOfCol1 = df.agg(round(sum("col1"),2)).as[Double].first

答案 1 :(得分:0)

首先让我们创建一个数据框:

import org.apache.spark.sql._
import org.apache.spark.sql.types._

val schema = List(
  StructField("col1", IntegerType, true),
  StructField("col2", IntegerType, true),
  StructField("col3", IntegerType, true)
)

val data=Seq(Row(10,100,1000),Row(20,200,2000),Row(30,300,3000))


val df = spark.createDataFrame(spark.sparkContext.parallelize(data),StructType(schema))
df.show()

+----+----+----+
|col1|col2|col3|
+----+----+----+
|  10| 100|1000|
|  20| 200|2000|
|  30| 300|3000|
+----+----+----+

现在我们有了数据框。 在分配值以收集所需结果时,我们可以使用模式匹配。由于df.first()返回了Row对象,因此我们可以执行以下操作:

val cols = df.columns.toList
val sums = cols.map(c => round(sum(c),2).cast("double"))

val Row(sumCol1: Double, sumCol2: Double, sumCol3: Double) = df.groupBy().agg(sums.head, sums.tail:_*).first()

sumCol1: Double = 60.0
sumCol2: Double = 600.0
sumCol3: Double = 6000.0