gpt4 book ai didi

scala - 如何创建 map 列以计算没有 udaf 的出现次数

转载 作者:行者123 更新时间:2023-12-04 16:25:53 25 4
gpt4 key购买 nike

我想创建一个 Map 列来计算出现次数。

例如:

+---+----+
| b| a|
+---+----+
| 1| b|
| 2|null|
| 1| a|
| 1| a|
+---+----+

会导致

+---+--------------------+
| b| res|
+---+--------------------+
| 1|[a -> 2.0, b -> 1.0]|
| 2| []|
+---+--------------------+

目前,在 Spark 2.4.6 中,我能够使用 udaf 实现它。

在碰到 Spark3 时,我想知道是否可以摆脱这个 udaf(我尝试使用新方法 aggregate 没有成功)

有没有一种有效的方法来做到这一点?(对于效率部分,我可以轻松测试)

最佳答案

这里是 Spark 3 解决方案:

import org.apache.spark.sql.functions._

df.groupBy($"b",$"a").count()
.groupBy($"b")
.agg(
map_from_entries(
collect_list(
when($"a".isNotNull,struct($"a",$"count"))
)
).as("res")
)
.show()

给予:

+---+----------------+
| b| res|
+---+----------------+
| 1|[b -> 1, a -> 2]|
| 2| []|
+---+----------------+

这里使用Aggregator的解决方案:

import org.apache.spark.sql.catalyst.encoders.ExpressionEncoder
import org.apache.spark.sql.expressions.Aggregator
import org.apache.spark.sql.functions._
import org.apache.spark.sql.Encoder

val countOcc = new Aggregator[String, Map[String,Int], Map[String,Int]] with Serializable {
def zero: Map[String,Int] = Map.empty.withDefaultValue(0)
def reduce(b: Map[String,Int], a: String) = if(a!=null) b + (a -> (b(a) + 1)) else b
def merge(b1: Map[String,Int], b2: Map[String,Int]) = {
val keys = b1.keys.toSet.union(b2.keys.toSet)
keys.map{ k => (k -> (b1(k) + b2(k))) }.toMap
}
def finish(b: Map[String,Int]) = b
def bufferEncoder: Encoder[Map[String,Int]] = implicitly(ExpressionEncoder[Map[String,Int]])
def outputEncoder: Encoder[Map[String, Int]] = implicitly(ExpressionEncoder[Map[String, Int]])
}

val countOccUDAF = udaf(countOcc)

df
.groupBy($"b")
.agg(countOccUDAF($"a").as("res"))
.show()

给予:

+---+----------------+
| b| res|
+---+----------------+
| 1|[b -> 1, a -> 2]|
| 2| []|
+---+----------------+

关于scala - 如何创建 map 列以计算没有 udaf 的出现次数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64339279/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com