我目前正在学习Spark并开发自定义机器学习算法。我的问题是.map()
和.mapValues()
之间的区别是什么?我明显不得不使用一个而不是另一个的情况?
答案 0 :(得分:52)
mapValues
仅适用于PairRDD,即RDD[(A, B)]
形式的RDD。在这种情况下,mapValues
仅对值(元组的第二部分)进行操作,而map
对整个记录进行操作(元组)关键和价值)。
换句话说,给定f: B => C
和rdd: RDD[(A, B)]
,这两个是相同的(几乎 - 见底部的评论):
val result: RDD[(A, C)] = rdd.map { case (k, v) => (k, f(v)) }
val result: RDD[(A, C)] = rdd.mapValues(f)
后者只是更短更清晰,因此当您只想转换值并按键保持按键时,建议使用mapValues
。
另一方面,如果你想要转换键(例如你想应用f: (A, B) => C
),你根本不能使用mapValues
,因为它只会传递值你的功能。
最后的差异涉及分区:如果您将任何自定义分区应用于您的RDD(例如使用partitionBy
),则使用map
将会忘记"由于密钥可能已经改变,该分区(结果将恢复为默认分区);但是,mapValues
会保留RDD上设置的任何分区程序。
答案 1 :(得分:4)
map
接受一个转换集合中每个元素的函数:
map(f: T => U)
RDD[T] => RDD[U]
当T
是一个元组时,我们可能只想对值进行操作 - 而不是键
mapValues采用一个函数,将输入中的值映射到输出中的值:mapValues(f: V => W)
RDD[ (K, V) ] => RDD[ (K, W) ]
mapValues
答案 2 :(得分:2)
当我们使用带有RDD的map()时,我们可以访问Key&值。我们很少有兴趣访问该值(& not key)。在这种情况下,我们可以使用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
Array [(String,(Int,Int))] = Array((英文,(65,1)),(数学,(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()
res1:Array [(String,Int)] = Array((英文,65),(数学,55))
答案 3 :(得分:1)
val inputrdd = sc.parallelize(Seq(("india", 250), ("england", 260), ("england", 180)))
(1)
map():-
val mapresult= inputrdd.map{b=> (b,1)}
mapresult.collect
Result-= Array(((india,250),1), ((england,260),1), ((english,180),1))
(2)
mapvalues():-
val mapValuesResult= inputrdd.mapValues(b => (b, 1));
mapValuesResult.collect
结果 -
Array((india,(250,1)), (england,(260,1)), (england,(180,1)))