Spark中的map vs mapValues

jti*_*usj 27 scala apache-spark

我目前正在学习Spark并开发定制机器学习算法.我的问题是之间的区别是什么.map().mapValues()有什么,我清楚必须使用一个,而不是其他情况?

Tza*_*har 58

mapValues仅适用于PairRDD,即表格的RDD RDD[(A, B)].在这种情况下,mapValues运行在只(元组的第二部分),而map在操作整个记录(的键和值的元组).

换句话说,给定f: B => Crdd: RDD[(A, B)],这两个是相同的(几乎 - 见底部的评论):

val result: RDD[(A, C)] = rdd.map { case (k, v) => (k, f(v)) }

val result: RDD[(A, C)] = rdd.mapValues(f)
Run Code Online (Sandbox Code Playgroud)

后者只是更短更清晰,所以当你只想转换值并保持按键原样时,建议使用mapValues.

另一方面,如果你想要转换键(例如你想要应用f: (A, B) => C),你根本无法使用,mapValues因为它只会将值传递给你的函数.

最后一个区别涉及分区:如果您将任何自定义分区应用于您的RDD(例如使用partitionBy),使用map将"忘记"该分区(结果将恢复为默认分区),因为密钥可能已更改; mapValues但是,保留RDD上设置的任何分区程序.

  • 谢谢!分区部分帮助我的部分. (4认同)
  • @gsamaras,它可能会对性能产生影响,因为如果您需要使用相同的密钥再次重新分区,丢失分区信息将迫使您进行洗牌。 (2认同)

vaq*_*han 5

当我们将 map() 与 Pair RDD 一起使用时,我们可以访问 Key 和 value。有几次我们只对访问值(而不是键)感兴趣。在这种情况下,我们可以使用 mapValues() 而不是 map()。

mapValues 示例

val inputrdd = sc.parallelize(Seq(("maths", 50), ("maths", 60), ("english", 65)))
val mapped = inputrdd.mapValues(mark => (mark, 1));

//
val reduced = mapped.reduceByKey((x, y) => (x._1 + y._1, x._2 + y._2))

reduced.collect
Run Code Online (Sandbox Code Playgroud)

Array[(String, (Int, Int))] = Array((english,(65,1)), (maths,(110,2)))

val average = reduced.map { x =>
                           val temp = x._2
                           val total = temp._1
                           val count = temp._2
                           (x._1, total / count)
                           }

average.collect()
Run Code Online (Sandbox Code Playgroud)

res1: Array[(String, Int)] = Array((english,65), (maths,55))