在PySpark的KeyVal RDD中为每个键收集前N个条目

时间:2019-06-16 12:03:48

标签: python apache-spark pyspark

我有一个带有大量KeyVal条目的RDD。相同的密钥将出现多次,我有兴趣提取每个密钥的前N个条目。对Spark非常陌生,到目前为止,我一直无法弄清楚如何做到这一点,因此将不胜感激。

输入看起来像:

rdd = sc.parallelize([('a',1),('a',2),('b',3),('a',5),('b',4),('b',6)])

每个键的前2个条目所需的最终输出:

output = {'a':[1,2], 'b':[3,4]}

如果我通常只对前n个条目感兴趣,那么我当然可以将take(n)应用于初始RDD。我正在寻找一种类似于take(n)函数的方法,但是要遍历每个键。如果我可以创建一个仅包含原始RDD所需子集的RDD,那很好。之后再收集到字典中就没什么问题了。

因此,中间输出(RDD样式)将是:

[('a',1),('a',2),('b',3),('b',4)]

我如何在PySpark中实现这一目标?

编辑:建议的重复问题专门要求使用reduceByKey的解决方案,在这种情况下不是必需的。

3 个答案:

答案 0 :(得分:2)

在这里听孩子...

nLength = 2
rdd.groupByKey().map(lambda x: (x[0], list(x[1])[:nLength]))

说明:

rdd.groupByKey()  

按键将RDD分组(在我们的示例中为“ a”或“ b”)。结果:
[('a',ResultIterable),('b',ResultIterable)]


.map(lambda x: (x[0], list(x[1])[:nLength]))

这部分创建一个元组:在左侧,键('a'或'b'),在右侧,我们从ResultIterable(x [1])创建一个列表,然后切割从0到nLength([:nLength])的列表。

享受!

答案 1 :(得分:0)

也许很简单,因为它可以完成这项工作:

rdd = sc.parallelize([('a',1),('a',2),('b',3),('a',5),('b',4),('b',6)])
n = 2
rdd.groupByKey().map(lambda x : (x[0], list(x[1])[:n])).collect()

输出:

[('b', [3, 4]), ('a', [1, 2])]

答案 2 :(得分:0)

尝试:

 def slice_list(s,no_of_values):
        return s[0:no_of_values]


rdd.groupByKey().map(lambda x: (x[0],slice_list( list(x[1]),2))).collect()