我想计算值的一部分,只有两个分区(其中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"和"黄色",一起被认为是"非红色"类型。
有什么想法吗?
答案 0 :(得分:1)
首先添加一列is_red
,以便更轻松地区分这两个群组。然后你可以groupBy
这个新列,分别获得两组中的每一组的总和。
要获得分数(部分),只需将每行的值除以正确的总和,同时考虑类型是否为红色。可以使用Spark中的when
和otherwise
来完成此部分。
以下是执行此操作的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