我正在学习Python中的Spark,并想知道有人可以解释行动foreach()
和转化map()
之间的区别吗?
rdd.map()
返回一个新的RDD,就像Python中的原始map函数一样。但是,我希望看到rdd.foreach()
函数并理解其中的差异。谢谢!
答案 0 :(得分:5)
一个非常简单的例子是rdd.foreach(print)
,它会打印RDD中每一行的值,但不会以任何方式修改RDD。
例如,这会产生一个数字为1 - 10的RDD:
>>> rdd = sc.parallelize(xrange(0, 10)).map(lambda x: x + 1)
>>> rdd.take(10)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
map
调用为每行计算了一个新值,并将其返回,以便我获得一个新的RDD。但是,如果我使用foreach
那将无用,因为foreach
不会以任何方式修改rdd:
>>> rdd = sc.parallelize(range(0, 10)).foreach(lambda x: x + 1)
>>> type(rdd)
<class 'NoneType'>
相反,在map
返回None
的函数上调用print
并不是很有用:
>>> rdd = sc.parallelize(range(0, 10)).map(print)
>>> rdd.take(10)
0
1
2
3
4
5
6
7
8
9
[None, None, None, None, None, None, None, None, None, None]
print
调用返回None
,因此映射只会为您提供一堆None
值,而您不想要这些值而您不想保存它们以便返回他们是浪费。 (请注意,1
,2
等行是print
正在执行,直到您拨打take
后才会显示,因为懒惰地执行了RDD。但是,RDD的内容只是一堆None
。
更简单地说,如果您关心函数的返回值,请调用map
。如果不这样做,请致电foreach
。
答案 1 :(得分:1)
映射是一种转换,因此当您执行映射时,您将一个函数应用于RDD中的每个元素,并返回一个新的RDD,可以调用其他转换或操作。
Foreach是一个动作,它接受每个元素并应用一个函数,但它不返回一个值。这在您必须调用对RDD执行某些计算并将结果记录到其他位置(例如数据库)或使用RDD中的每个元素调用REST API时尤其有用。
例如,假设您有一个RDD,其中包含许多您希望在另一个系统中登录的查询。查询存储在RDD中。
queries = <code to load queries or a transformation that was applied on other RDDs>
然后,您希望通过调用另一个API
将这些查询保存在另一个系统中import urllib2
def log_search(q):
response = urllib2.urlopen('http://www.bigdatainc.org/save_query/' + q)
queries.foreach(call_search)
现在您已经在RDD的每个元素上执行了log_query。如果你做了一张地图,那么在你召集一个动作之前,什么都不会发生。