索引最常出现的元素

时间:2015-01-27 10:56:33

标签: scala apache-spark

我有一个表格

的数组
val array: Array[(Int, (String, Int))] = Array(
  (idx1,(word1,count1)),
  (idx2,(word2,count2)),
  (idx1,(word1,count1)),
  (idx3,(word3,count1)),
  (idx4,(word4,count4)))

我想从每个索引(idx1,idx2,....)获取此数组的前10个和后10个元素。基本上我想要每个索引值的前10个最常见和最低10个最少出现的元素。

请建议如何以最有效的方式实现火花。 我已经尝试过为每个索引使用for循环,但这会使程序太慢而且顺序运行。

一个例子是:

(0,("apple",1))
(0,("peas",2))
(0,("banana",4))

(1,("peas",2))
(1,("banana",1))
(1,("apple",3))

(2,("NY",3))
(2,("London",5))
(2,("Zurich",6))

(3,("45",1))
(3,("34",4))
(3,("45",6))


Suppose I do top 2 on this set output would be 

    (0,("banana",4))
    (0,("peas",2))

    (1,("apple",3))
    (1,("peas",2))

    (2,("Zurich",6))
    (2,("London",5))

    (3,("45",6))
    (3,("34",4))

我也需要同样的底部2

2 个答案:

答案 0 :(得分:0)

不确定火花,但我认为你可以使用类似的东西:

def f(array: Array[(Int, (String, Int))], n:Int) = 
  array.groupBy(_._1)
    .map(pair => (
           pair._1, 
           pair._2.sortBy(_._2).toList
         ) 
     )
    .map(pair => (
           pair._1, 
           (
              pair._2.take(Math.min(n, pair._2.size)),          
              pair._2.drop(Math.max(0, pair._2.size - n))
           )
         )
     )

groupBy通过频率将索引映射返回到条目的排序列表中。在此之后,将这些条目映射到一对列表,一个列表包含前n个元素,另一个包含底部n个元素。请注意,您可以用_替换所有命名参数,为清楚起见,我这样做了。

此版本假设您始终对计算top和bot n元素感兴趣,因此只需一次通过。如果你通常只需要两个中的一个,那么在toList之后立即添加.take或.drop会更有效。

答案 1 :(得分:0)

我理解这相当于通过在(K,V)对上使用groupByKey生成整个列列表,然后对其进行排序操作。尽管操作是正确的,但在典型的spark环境中,groupByKey操作将涉及大量的shuffle输出,这可能导致操作效率低下。