2016-01-13 56 views
13

我刚开星火的窍门,我有一个需要被映射到一个rdd功能,但使用全球字典来RDD:广播字典中PySpark

from pyspark import SparkContext 

sc = SparkContext('local[*]', 'pyspark') 

my_dict = {"a": 1, "b": 2, "c": 3, "d": 4} # at no point will be modified 
my_list = ["a", "d", "c", "b"] 

def my_func(letter): 
    return my_dict[letter] 

my_list_rdd = sc.parallelize(my_list) 

result = my_list_rdd.map(lambda x: my_func(x)).collect() 

print result 

上面给出的预期结果;但是,我真的不确定我使用全局变量my_dict。似乎字典的副本是由每个分区创建的。它只是不舒服..

它看起来像broadcast是我在找什么。然而,当我尝试使用它:

my_dict_bc = sc.broadcast(my_dict) 

def my_func(letter): 
    return my_dict_bc[letter] 

我得到以下错误:

TypeError: 'Broadcast' object has no attribute '__getitem__ 

这似乎在暗示,我不能播放字典。

我的问题:如果我有一个使用全局字典的函数,需要将其映射到rdd,那么正确的方法是什么?

我的例子很简单,但实际上my_dictmy_list要大得多,而my_func比较复杂。

回答

15

您忘记了一些有关Broadcast对象的重要内容,它们有一个名为value的属性,用于存储数据。

因此,你需要修改my_func到这样的事情:

my_dict_bc = sc.broadcast(my_dict) 

def my_func(letter): 
    return my_dict_bc.value[letter] 
+0

我看到!所以,当我加'my_dict_bc.value'它工作正常。 “广播”是一种标准的方法来处理被共享的对象,对吗? – Akavall

+0

是的,这是一个好习惯,但是如果字典不是太大,那么你可以使用全局对象而没有任何问题 –

+0

有意义。谢谢。 – Akavall