我正在尝试以下代码,它为RDD中的每一行添加一个数字,并使用PySpark返回一个RDD列表。
from pyspark.context import SparkContext
file = "file:///home/sree/code/scrap/sample.txt"
sc = SparkContext('local', 'TestApp')
data = sc.textFile(file)
splits = [data.map(lambda p : int(p) + i) for i in range(4)]
print splits[0].collect()
print splits[1].collect()
print splits[2].collect()
输入文件(sample.txt)中的内容为:
1
2
3
我期待这样的输出(在rdd中分别添加0,1,2的数字):
[1,2,3]
[2,3,4]
[3,4,5]
而实际输出是:
[4, 5, 6]
[4, 5, 6]
[4, 5, 6]
这意味着理解仅使用变量i的值3,而不考虑范围(4)。
为什么会出现这种情况?
答案 0 :(得分:4)
这是因为Python后期绑定而不是(Py)Spark特有的。使用i
时将查找lambda p : int(p) + i
,而不是在定义时查找def f(i):
def _f(x):
try:
return int(x) + i
except:
pass
return _f
data = sc.parallelize(["1", "2", "3"])
splits = [data.map(f(i)) for i in range(4)]
[rdd.collect() for rdd in splits]
## [[1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6]]
。通常它意味着何时被调用,但在这个特定的上下文中,它被序列化以发送给工人。
你可以这样做:
(IsNUll((CAST(MHSE_ as varchar (20))),'') + ' ' + isnull(MDIRCT,'') + ' ' + IsNull(MSTRT,'') + ' ' + isnull(MSTTYP,'')) as FULLADDRESS
答案 1 :(得分:2)
这是因为lambdas引用了i via引用!它与火花无关。 See this
你可以试试这个:
a =[(lambda y: (lambda x: y + int(x)))(i) for i in range(4)]
splits = [data.map(a[x]) for x in range(4)]
或一行
splits = [
data.map([(lambda y: (lambda x: y + int(x)))(i) for i in range(4)][x])
for x in range(4)
]