Scala,Spark:查找N个映射的逐元素平均值



我有N个映射(Map[String,Double](,每个映射都有相同的键集。让我们说如下:

map1 = ("elem1": 2.0, "elem2": 4.0, "elem3": 3.0)
map2 = ("elem1": 4.0, "elem2": 1.0, "elem3": 1.0)
map3 = ("elem1": 3.0, "elem2": 10.0, "elem3": 2.0)

我需要返回一个新映射,其中包含这些输入映射的逐元素平均值:

resultMap = ("elem1": 3.0, "elem2": 5.0, "elem3": 2.0)

在 scala 中做到这一点最干净的方法是什么?最好不使用额外的外部库。

这一切都发生在Spark*中。因此,任何建议火花特定用法的答案都可能会有所帮助。

一种选择是将所有地图转换为Seq,将它们合并为单个Seq,按键分组并取值的平均值:

val maps = Seq(map1, map2, map3)
maps.map(_.toSeq).reduce(_++_).groupBy(_._1).mapValues(x => x.map(_._2).sum/x.length)
// res6: scala.collection.immutable.Map[String,Double] = Map(elem1 -> 3.0, elem3 -> 2.0, elem2 -> 5.0)

由于您的问题被标记为apache-spark,因此您可以通过将地图组合成RDD[Map[String, Double]]作为

scala>     val rdd = sc.parallelize(Seq(Map("elem1"-> 2.0, "elem2"-> 4.0, "elem3"-> 3.0),Map("elem1"-> 4.0, "elem2"-> 1.0, "elem3"-> 1.0),Map("elem1"-> 3.0, "elem2"-> 10.0, "elem3"-> 2.0)))
rdd: org.apache.spark.rdd.RDD[scala.collection.immutable.Map[String,Double]] = ParallelCollectionRDD[1] at parallelize at <console>:24

然后,您可以使用flatMap映射的条目平展单独的行,并使用groupBy函数进行键和sum分组值,并使用分组地图的大小对其进行devide。您应该获得所需的输出

scala> rdd.flatMap(row => row).groupBy(kv => kv._1).mapValues(values => values.map(value => value._2).sum/values.size)
res0: org.apache.spark.rdd.RDD[(String, Double)] = MapPartitionsRDD[5] at mapValues at <console>:27
scala> res0.foreach(println)
[Stage 0:>                                                          (0 + 0) / 4](elem2,5.0)
(elem3,2.0)
(elem1,3.0)

希望答案对您有所帮助

最新更新