将Scala方法转换为Spark

时间:2014-05-21 16:40:51

标签: scala apache-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都转换为数组,但我认为这对于大型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)
  }

2 个答案:

答案 0 :(得分:2)

不要collect RDD。它将所有数据提取到一台机器上。更改输入,使其按否定距离(RDD[Double, (String, String)])键入,然后使用RDD.top(k)

答案 1 :(得分:1)

RDD确实有sortByKey方法,它通过第一个元素对对的RDD进行排序,因此如果您可以创建RDD[(Double, (String, String))]而不是RDD[((String, String), Double)](或只是调用rdd.map(p => (p._2, p._1)) ,你可以直接翻译算法。它也有take,但文档说:

  

返回包含数据集的前n个元素的数组。请注意,这当前不是并行执行的。相反,驱动程序计算所有元素。

所以我不希望这个很好

此外,如果数据适合一台机器,那么只使用Arrays(或并行集合)可能会更快。 Spark尽其所能来减少开销,但分布式排序无论如何都会有一些开销!

此外,如果您只需要n元素,则对整个数组/ RDD /其他集合进行排序是一个坏主意(同样,尤其是在您想要使用Spark的情况下)。您需要一个类似于Worst-case O(n) algorithm for doing k-selectionIn an integer array with N elements , find the minimum k elements?中所述的选择算法。不幸的是,它们在Scala标准库或Spark(我知道)中都不可用。