Spark Dataframe GroupBy并计算Complex聚合函数

时间:2017-10-04 07:51:45

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

使用Spark数据帧,我需要使用下面的方法计算百分比 复杂的公式:

分组" KEY"并计算" re_pct" as(sum(sa)/ sum(sa /(pct / 100)))* 100

对于实例,输入数据帧是

val values1 = List(List("01", "20000", "45.30"), List("01", "30000", "45.30"))
  .map(row => (row(0), row(1), row(2)))

val DS1 = values1.toDF("KEY", "SA", "PCT")
DS1.show()

+---+-----+-----+
|KEY|   SA|  PCT|
+---+-----+-----+
| 01|20000|45.30|
| 01|30000|45.30|
+---+-----+-----+

预期结果:

+---+-----+--------------+
|KEY|    re_pcnt         |
+---+-----+--------------+
| 01|   45.30000038505   |
+---+-----+--------------+

我试过计算如下

    val result = DS1.groupBy("KEY").agg(((sum("SA").divide(
  sum(
    ("SA").divide(
      ("PCT").divide(100)
    )
  )
)) * 100).as("re_pcnt"))

但是面对错误:(36,16)值除以不是String的成员(" SA")。divide({

有关实施上述逻辑的任何建议吗?

2 个答案:

答案 0 :(得分:3)

您可以尝试导入spark.implicits._,然后使用$来引用列。

val spark = SparkSession.builder.getOrCreate()
import spark.implicits._

val result = DS1.groupBy("KEY")
  .agg(((sum($"SA").divide(sum(($"SA").divide(($"PCT").divide(100))))) * 100)
  .as("re_pcnt"))

这将为您提供所需的输出。

如果您不想导入,可以始终使用col()命令代替$

可以使用字符串作为agg()函数的输入,并使用expr()。但是,输入字符串需要稍微改变一下。以下结果与之前的结果完全相同,但使用的是字符串:

val opr = "sum(SA)/(sum(SA/(PCT/100))) * 100"
val df = DS1.groupBy("KEY").agg(expr(opr).as("re_pcnt"))

请注意,.as("re_pcnt")必须位于agg()方法内,不能在外面。

答案 1 :(得分:0)

您的代码几乎完美无缺。你只需要把'' $'符号以指定您传递列:

val result = DS1.groupBy($"KEY").agg(((sum($"SA").divide(
  sum(
    ($"SA").divide(
      ($"PCT").divide(100)
    )
  )
)) * 100).as("re_pcnt"))

这是输出:

result.show()
+---+-------+                                                                   
|KEY|re_pcnt|
+---+-------+
| 01|   45.3|
+---+-------+