我有一个非常简单的代码:
def fun(x, n):
return (x, n)
rdds = []
for i in range(2):
rdd = sc.parallelize(range(5*i, 5*(i+1)))
rdd = rdd.map(lambda x: fun(x, i))
rdds.append(rdd)
a = sc.union(rdds)
print a.collect()
我原本期望输出如下:
[(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 1), (6, 1), (7, 1), (8, 1), (9, 1)]
但是,输出如下:
[(0, 1), (1, 1), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1), (7, 1), (8, 1), (9, 1)]
至少可以说这是令人困惑的。
看来,由于对RDD的懒惰评估,用于创建RDD的i
的值是它在调用collect()
时所承受的值,即1(从上次运行开始) for
循环。)
现在,元组的两个元素都来自i
。
但似乎,对于元组的第一个元素,i
的值为0和1,而元组i
的第二个元素的值为2。
有人可以解释一下发生了什么吗?
感谢。
答案 0 :(得分:2)
只需更改
rdd = rdd.map(lambda x: fun(x, i))
到
rdd = rdd.map(lambda x, i=i: (x, i))
这只是关于Python,请看这个
https://docs.python.org/2.7/tutorial/controlflow.html#default-argument-values
答案 1 :(得分:0)
sc.parallelize()
是一个即时执行的动作。因此,将使用i
的值,即0
和1
。
但是在rdd.map()
的情况下,当您稍后致电i
时,将仅使用collect()
的最后一个值。
rdd = sc.parallelize(range(5*i, 5*(i+1)))
rdd = rdd.map(lambda x: fun(x, i))
这里rdd.map不会变换rdd,它只会创建DAG(Directed Acyclic Graph),即lambda函数不会应用于rdd的元素。
当你调用collect()时,将调用lambda函数,但到那时i
的值为1.如果在调用collect之前重新分配i=10
,那么{{1}的值将被使用。