[英]Converting a Scala method to Spark
下面的Scala方法返回Array
的k个最近邻居:
def getNearestNeighbours(distances: Array[((String, String), Double)], k: Int, label: String) = { //| label: String)List[((String, String), Double)]
distances.filter(v => v._1._1.equals(label) || v._1._2.equals(label)).sortBy(_._2).take(k)
}
我想并行运行此功能。 我可以尝试将Array
转换为RDD
但类型RDD
不支持函数.sortBy(_._2).take(k)
是否可以在Spark / Scala中模拟此方法?
一种可能的解决方案是修改该方法,以便每次调用该方法时RDD都转换为Array,但是我认为这对于大型RDD而言在计算上是昂贵的? :
def getNearestNeighbours(distances: RDD[((String, String), Double)], k: Int, label: String) = { //| label: String)List[((String, String), Double)]
distances.collect.filter(v => v._1._1.equals(label) || v._1._2.equals(label)).sortBy(_._2).take(k)
}
不要collect
RDD。 它将所有数据拉到一台计算机上。 更改您的输入,使其以负距离为键( RDD[Double, (String, String)]
),然后使用RDD.top(k)
。
RDD确实具有sortByKey
方法,该方法按第一个元素对对的RDD进行排序,因此,如果可以创建RDD[(Double, (String, String))]
而不是RDD[((String, String), Double)]
(或仅调用rdd.map(p => (p._2, p._1)
),您可以直接翻译该算法。它也带有take
,但是文档中说:
返回具有数据集的前n个元素的数组。 请注意,当前这不是并行执行的。 相反,驱动程序会计算所有元素。
所以我认为这不会很好 。
此外,如果数据适合在一台计算机上,则仅使用数组(或并行集合)可能会更快。 Spark尽其所能使开销最小化,但是无论如何,分布式排序都会有一些开销!
另外,如果只需要最少的n
元素,则对整个数组/ RDD /其他集合进行排序是一个坏主意(同样,尤其是在您想使用Spark的情况下)。 您需要像最差情况O(n)算法中所述的选择算法来进行k选择,还是在具有N个元素的整数数组中找到最小k个元素? 。 不幸的是,它们在Scala标准库或Spark(据我所知)中不可用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.