Pyspark Pypark,按键相交
例如,我在PySpark中有两个RDD:Pyspark Pypark,按键相交,pyspark,rdd,Pyspark,Rdd,例如,我在PySpark中有两个RDD: ((0,0), 1) ((0,1), 2) ((1,0), 3) ((1,1), 4) 第二是公正 ((0,1), 3) ((1,1), 0) 我想让第一个RDD和第二个RDD相交。实际上,第二个RDD必须扮演第一个RDD的掩码角色。输出应为: ((0,1), 2) ((1,1), 4) 它表示来自第一个RDD的值,但仅适用于来自第二个RDD的键。两个RDD的长度不同 我有一些解决方案(必须证明),但类似这样: rdd3 = rdd1.cartes
((0,0), 1)
((0,1), 2)
((1,0), 3)
((1,1), 4)
第二是公正
((0,1), 3)
((1,1), 0)
我想让第一个RDD和第二个RDD相交。实际上,第二个RDD必须扮演第一个RDD的掩码角色。输出应为:
((0,1), 2)
((1,1), 4)
它表示来自第一个RDD的值,但仅适用于来自第二个RDD的键。两个RDD的长度不同
我有一些解决方案(必须证明),但类似这样:
rdd3 = rdd1.cartesian(rdd2)
rdd4 = rdd3.filter(lambda((key1, val1), (key2, val2)): key1 == key2)
rdd5 = rdd4.map(lambda((key1, val1), (key2, val2)): (key1, val1))
我不知道,这个解决方案有多有效。想听听有经验的Spark程序员的意见……也许我们不应该将此过程视为加入。你不是真的想连接两个数据集,而是想从另一个数据集中减去一个数据集 我将陈述我从你的问题中所作的假设
想法1:协同组(我认为可能是最快的方法)。它基本上是计算两个数据集的交集
rdd1 = sc.parallelize([((0,0), 1), ((0,1), 2), ((1,0), 3), ((1,1), 4)])
rdd2 = sc.parallelize([((0,1), 3), ((1,1), 0)])
intersection = rdd1.cogroup(rdd2).filter(lambda x: x[1][0] and x[1][1])
final_rdd = intersection.map(lambda x: (x[0], list(x[1][0]))).map(lambda (x,y): (x, y[0]))
想法2:按键减去
rdd1 = sc.parallelize([((0,0), 1), ((0,1), 2), ((1,0), 3), ((1,1), 4)])
rdd2 = sc.parallelize([((0,1), 3), ((1,1), 0)])
unwanted_rows = rdd1.subtractByKey(rdd2)
wanted_rows = rdd1.subtractByKey(unwanted_rows)
我不能100%确定这是否比你的方法快。它确实需要两个subtractByKey
操作,这可能会很慢。此外,此方法不保留顺序(例如,((0,1),2)
,尽管在第一个数据集中排名第一,但在最终数据集中排名第二)。但我无法想象这有多重要
至于哪一个更快,我想这取决于你的cartersian连接需要多长时间。映射和过滤往往比subtractByKey
所需的洗牌操作要快,但当然cartesian
是一个耗时的过程
无论如何,我想你可以试试这个方法,看看它是否适合你
性能改进的旁注,取决于RDD的大小
如果
rdd1
小到可以保存在主存中,那么如果您广播它,然后对其流式传输rdd2
,减法过程可以大大加快。然而,我承认这种情况很少发生 多谢各位。我想,这应该是一种根据结果对RDD进行分类的方法。再次非常感谢。我还建议您查看交叉口。现在,它似乎只在整行匹配时才起作用,这对您的用例不起作用,但我想知道您是否可以操纵intersection
来只处理键值对的交集。如果我弄明白了,我会更新我的答案。交集是另一个故事,我真的在寻找键的交集,而不是值(当然,这也是你告诉我的)。但我会花点时间分析一下你的建议。谢谢,我在cogroup
中添加了一些信息,它允许您仅在维护值的同时匹配键。