给定两个大的键值对RDD(d1
和d2
),两者都由唯一的 ID 键和 vector 值组成(例如RDD[Int,DenseVector]
),我需要映射d1
,以便为每个元素获取d2
中最接近元素的 ID ,使用之间的欧氏距离度量标准载体
我还没有找到使用标准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
答案 0 :(得分:2)
RDD上的转换只能应用于驱动程序端,因此嵌套不起作用。正如@davidgriffin指出的那样,你可以使用cartesian
。对于您的使用案例,您可能希望使用reduceByKey
进行操作,并在您的reduce by键中,您可以跟踪最小距离。