Scala,Spark:找到N个地图的元素平均值

时间:2017-08-05 23:42:22

标签: scala apache-spark reduce

我有N个地图(Map [String,Double]),每个地图都有相同的密钥集。让我们说出如下内容:

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

我需要返回一个新的地图,其中包含那些输入地图的元素平均值:

[
   {
       key: some_key,
       payload: { ... }
   }, 
   {
       key: some_key,
       payload: { ... }
   }, 
   {
       key: some_key,
       payload: { ... }
   }, 
   ...
]

scala中最干净的方法是什么?最好不要使用额外的外部库。

这一切都发生在Spark *中。因此,任何暗示特定于火花的使用的答案都可能有所帮助。

2 个答案:

答案 0 :(得分:2)

一种选择是将所有地图转换为Seqs,将它们合并为单个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)

答案 1 :(得分:1)

由于您的问题已使用 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)

希望答案有用