spark数据帧基于条件的列总和

时间:2018-03-27 17:04:19

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

我想计算值的一部分,只有两个分区(其中type == red,其中type = = red)

ID     | type        | value
-----------------------------
  1    |    red      |  10
  2    |    blue     |  20
  3    |    yellow   |  30

结果应为:

ID     | type        | value | portion
-----------------------------
  1    |    red      |  10   | 1
  2    |    blue     |  20   |0.4
  3    |    yellow   |  30   |0.6

spark中的普通窗口函数仅支持整列的分区,但我需要" blue"和"黄色",一起被认为是"非红色"类型。

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

首先添加一列is_red,以便更轻松地区分这两个群组。然后你可以groupBy这个新列,分别获得两组中的每一组的总和。

要获得分数(部分),只需将每行的值除以正确的总和,同时考虑类型是否为红色。可以使用Spark中的whenotherwise来完成此部分。

以下是执行此操作的Scala代码。有sortBy因为使用groupBy时无法保证结果的顺序。对于排序,下面的sum1将包含所有非红色类型的总和,而sum2是红色类型的总和。

val sum1 :: sum2 :: _ = df.withColumn("is_red", $"type" === lit("red"))
  .groupBy($"is_red")
  .agg(sum($"value"))
  .collect()
  .map(row => (row.getAs[Boolean](0), row.getAs[Long](1)))
  .toList
  .sortBy(_._1)
  .map(_._2)

val df2 = df.withColumn("portion", when($"is_red", $"value"/lit(sum2)).otherwise($"value"/lit(sum1)))

可以使用is_red删除额外的drop列。

答案 1 :(得分:1)

受Shaido的启发,我使用了额外的列head { title("XML encoding with Kotlin") } 和火花窗口功能。但我不确定哪一个表现更好。

is_red