当通过广播应用地图转换时,pyspark Udf无法按预期工作吗?

时间:2018-12-07 14:28:30

标签: apache-spark pyspark rdd user-defined-functions

我有两个类似的清单

l=[['A', 'B', 'C'], ['A', 'C'], ['A', 'B', 'C'], ['A', 'B'],['B','C'],['B']]
x=[('A', 'B'), ('A', 'C')]

我想从列表l中删除所有不包含列表tuple中任何x中所有元素的元素。换句话说,tuple中至少应有一个x,其中所有元组的所有项都存在于l的元素中。

基于我的last question,在python中为我提供了以下解决方案:

print([l_ for l_ in l if any(all(e in l_ for e in x_) for x_ in x)])

产生期望的输出:

[['A', 'B', 'C'], ['A', 'C'], ['A', 'B', 'C'], ['A', 'B']]

现在,我尝试使用pyspark rdd复制相同的操作,但是没有得到预期的结果。

这是我尝试过的:

rddsort=sc.parallelize(l)
broadcastVar = sc.broadcast(x)

def flist(unique_product_List,x):
    filter_list = [
        l_ for l_ in unique_product_List 
        if any(all(e in l_ for e in x_) for x_ in x)
    ]

    return filter_list

rddsort=rddsort.map(lambda flist(x[0],broadcastVar.value)) 
print(rddsort.collect())

结果是我得到了一个空列表清单:

[[], [], [], [], [], []]

但是我的预期结果应该与上面相同。

1 个答案:

答案 0 :(得分:2)

您需要在rdd(不是地图)上使用过滤器。过滤器将检查每行的条件,并删除不匹配的条件。这里的条件是,行值(列表_l = l [0])应该具有x中列表之一中的所有元素。

l=[['A', 'B', 'C'], ['A', 'C'], ['A', 'B', 'C'], ['A', 'B'],['B','C'],['B']]
x=[('A', 'B'), ('A', 'C')]
rddsort=sc.parallelize(l)

rddsort=rddsort.filter(lambda l_: any(all(e in l_ for e in x_) for x_ in x)) 
print(rddsort.collect())

输出

[['A', 'B', 'C'], ['A', 'C'], ['A', 'B', 'C'], ['A', 'B']]

更新: 在函数中具有广播变量:

l=[['A', 'B', 'C'], ['A', 'C'], ['A', 'B', 'C'], ['A', 'B'],['B','C'],['B']]
x=[('A', 'B'), ('A', 'C')]
rddsort=sc.parallelize(l)
broadcastVar = sc.broadcast(x)

def flist(row):
    filter_flag = any(all(e in l_ for e in x_) for x_ in broadcastVar.value)
    return filter_flag

rddsort=rddsort.filter(flist) 
print(rddsort.collect())