[英]Spark: How to map an RDD when access to another RDD is required
给定两个大的键值对RDD( d1
和d2
),两者都由唯一的ID键和矢量值组成(例如RDD[Int,DenseVector]
),我需要映射d1
以便为其每个元素获取ID使用矢量之间的欧氏距离度量在d2
最接近的元素。
我还没有找到使用标准RDD转换的方法。 我知道Spark中不允许嵌套的RDD,但是,如果可能的话,一个简单的解决方案是:
d1.map((k,v) => (k, d2.map{case (k2, v2) => val diff = (v - v2); (k2, sqrt(diff dot diff))}
.takeOrdered(1)(Ordering.by[(Double,Double), Double](_._2))
._1))
此外,如果d1
很小,我可以使用Map(例如d1.collectAsMap()
)并遍历其每个元素,但由于数据集大小,这不是一个选项。
在Spark中有这种转换的替代方案吗?
编辑1:
使用@holden和@ david-griffin建议我使用cartesian()
和reduceByKey()
解决了这个问题。 这是脚本(假设sc
为SparkContext
并使用Breeze库)。
val d1 = sc.parallelize(List((1,DenseVector(0.0,0.0)), (2,DenseVector(1.0,0.0)), (3,DenseVector(0.0,1.0))))
val d2 = sc.parallelize(List((1,DenseVector(0.0,0.75)), (2,DenseVector(0.0,0.25)), (3,DenseVector(1.0,1.0)), (4,DenseVector(0.75,0.0))))
val d1Xd2 = d1.cartesian(d2)
val pairDistances = d1Xd2.map{case ((k1, v1), (k2, v2)) => (k1, (k2, sqrt(sum(pow(v1-v2,2)))))}
val closestPoints = pairDistances.reduceByKey{case (x, y) => if (x._2 < y._2) x else y }
closestPoints.foreach(s => println(s._1 + " -> " + s._2._1))
获得的输出是:
1 -> 2
2 -> 4
3 -> 1
RDD上的转换只能应用于驱动程序端,因此嵌套映射将不起作用。 正如@davidgriffin指出你可以使用cartesian
。 对于您的用例,您可能希望使用reduceByKey
跟随它,并且在您的reduce by键中,您可以跟踪最小距离。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.