我的目标是让每个数据点的k个最近邻居。我想避免使用带有查询的for循环并在每个rdd_distance
点上同时使用其他内容,但我无法弄清楚如何执行此操作。
parsedData = RDD[Object]
//Object have an id and a vector as attribute
//sqdist1 output is a Double
var rdd_distance = parsedData.cartesian(parsedData)
.flatMap { case (x,y) =>
if(x.get_id != y.get_id)
Some((x.get_id,(y.get_id,sqdist1(x.get_vector,y.get_vector))))
else None
}
for(ind1 <- 1 to size) {
val ind2 = ind1.toString
val tab1 = rdd_distance.lookup(ind2)
val rdd_knn0 = sc.parallelize(tab1)
val tab_knn = rdd_knn0.takeOrdered(k)(Ordering[(Double)].on(x=>x._2))
}
如果不使用带循环的for循环,是否可以这样做?
答案 0 :(得分:2)
此代码解决了您的问题(但parsedData
的数量很大时效率低下。)
rdd_distance.groupByKey().map {
case (x, iterable) =>
x -> iterable.toSeq.sortBy(_._2).take(k)
}
所以这是更合适的解决方案。
import org.apache.spark.mllib.rdd.MLPairRDDFunctions._
rdd_distance.topByKey(k)(Ordering.by(-_._2)) // because smaller is better.
请注意,此代码包含Spark 1.4.0
。如果您使用的是早期版本,请使用此代码https://github.com/apache/spark/blob/master/mllib/src/main/scala/org/apache/spark/mllib/rdd/MLPairRDDFunctions.scala
topBykey
的想法是将BoundedPriorityQueue
与aggregateByKey
一起使用,保留前k项。