在另一个RDD的基础上修剪一个RDD

时间:2016-11-26 09:04:07

标签: python apache-spark pyspark

是否有一种方法可以在一个RDD中基于另一个RDD过滤元素,即使它们不共享相同的密钥?

我有两个RDD - abc和xyz

abc.collect()看起来像这样

[[a,b,c],[a,c,g,e],[a,e,b,x],[b,c]]

xyz.collect()看起来像这样

[a,b,c]

现在我想过滤掉RDD abc中xyz中不存在的所有元素。

在上述操作之后,RDD Abc应如下所示:

[[a,b,c],[a,c],[a,b],[b,c]]

我写了一段代码如下:

def prune(eachlist):
    for i in eachlist:
        if i in xyz:
            return i

abc = abc.map(prune)

然而,这给了我这个错误:

Exception: It appears that you are attempting to broadcast an RDD or reference an RDD from an action or transformation. RDD transformations and actions can only be invoked by the driver, not inside of other transformations; for example, rdd1.map(lambda x: rdd2.values.count() * x) is invalid because the values transformation and count action cannot be performed inside of the rdd1.map transformation

我已经尝试了过滤器,查找而不是地图无济于事。我一直得到同样的错误。

我知道我可以对xyz进行收集操作并解决此错误,但我在大型数据集上运行此操作并执行.collect()会因为内存过多而导致我的AWS服务器死亡。因此,我需要在不使用.collect()或任何此类等价的昂贵操作的情况下执行此操作。

1 个答案:

答案 0 :(得分:2)

你可以:

# Add index
abc.zipWithIndex() \
    # Flatten values
    .flatMap(lambda x: [(k, x[1]) for k in x[0]]) \
    # Join with xyz (works as filter)
    .join(xyz.map(lambda x: (x, None))) \
    # Group back by index
    .map(lambda x: (x[1][0], x[0])) \
    .groupByKey() \
    .map(lambda x: list(x[1]))

或者您可以在xyz上创建Bloom过滤器,并使用它来映射abc