我有RDD[(Key,Iterable[(Name,Value)])]
。
我正在尝试获取Name
中的所有值,以便我可以获得Name
的所有唯一匹配项,然后创建Index
,以便创建结果RDD
RDD[(Key,Iterable[(Index,Value)])]
。
输入示例:
(4048,CompactBuffer(("a",3.0), ("b",9.0), ("c",14.0))
(4049,CompactBuffer(("a",2.0), ("c",14.0))
(4050,CompactBuffer(("b",2.0), ("d",10.0))
输出示例:
(4048,CompactBuffer((1,3.0), (2,9.0), (3,14.0))
(4049,CompactBuffer((1,2.0), (3,12.0))
(4050,CompactBuffer((2,2.0), (4,10.0))
答案 0 :(得分:3)
如果我理解你想要什么,这样的事情应该有效:
val rdd: RDD[K, Iterable[N, V]] = ???
val nameIndexMap = rdd.flatMap(_._2.map(nv => nv._1))
.distinct
.collect
.zipWithIndex
.toMap
val newRDD = rdd.mapValues(xs => xs.map(nv => (nameIndexMap(nv._1), nv._2)))
如果nameIndexMap
很大或者会多次使用,那么您可能希望使用广播,例如像这样的东西
val nameIndexMapBc = sc.broadcast(nameIndexMap) //sc is the SparkContext
val newRDD = rdd.mapValues(xs => xs.map(nv => (nameIndexMap.value)(nv._1), nv._2)))
答案 1 :(得分:1)
如果名称空间的基数高,你可以对jasonl的anwer进行一些小的补充,你可以执行类似的转换,避免将名字收集到驱动程序内存中:
val named = rdd.flatMap { case (key, values) => values.map { case (name, value) => (name, (key, value)) } }
val nameMap = named.map(_._1).distinct().zipWithUniqueId()
val indexed = named.join(nameMap).map { case (name, ((key, value), index)) => (key, (index, value)) }.groupByKey