我正在应用地图,然后使用pyspark在RDD上进行reduceByKey转换。我尝试了以下两种语法,它们似乎都有效:
案例1:
my_rdd_out = my_rdd.map(lambda r: [r['my_id'], [[r['my_value']]]])\
.reduceByKey(lambda a, b: a+b)\
.map(lambda r: r[1])
案例2:
my_rdd_out = my_rdd.map(lambda r: (r['my_id'], [[r['my_value']]]))\
.reduceByKey(lambda a, b: a+b)\
.map(lambda r: r[1])
这里的r是班级from pyspark.sql import Row
。
在情况1中,地图输出对在括号中;在情况2中,地图输出对在括号中。虽然两者都有效,但我想知道使用[]和()来表示一对将在以后作为reduceByKey的输入之间有什么区别吗?谢谢!
答案 0 :(得分:1)
python中tuple
和list
之间的区别在于tuple
对象是不可变的,因此它们是可清除的。 list
个对象不可清除,因为它们可以使用它们的引用进行修改。
在您的情况下,您可以使用其中任何一种(或reduceByKey
方法不适用于元组和列表),只是方便避免在您使用时将其转换为另一种方法从一些调用者那里获取对象(该方法只需要遍历集合,不关心它是什么类型的集合。)
此处是从here
取消的reduceByKey
的实现
def reduceByKey(func, iterable):
"""Reduce by key.
Equivalent to the Spark counterpart
Inspired by http://stackoverflow.com/q/33648581/554319
1. Sort by key
2. Group by key yielding (key, grouper)
3. For each pair yield (key, reduce(func, last element of each grouper))
"""
get_first = lambda p: p[0]
get_second = lambda p: p[1]
# iterable.groupBy(_._1).map(l => (l._1, l._2.map(_._2).reduce(func)))
return map(
lambda l: (l[0], reduce(func, map(get_second, l[1]))),
groupby(sorted(iterable, key=get_first), get_first)
)
在您的示例中,您有tuple(<something>).reduceByKey(lambda <something>)
。显然,iterable是tuple
而func
是lambda表达式。
如您所见,输入只需要是可迭代的。甚至不需要索引访问。
你可以通过set
,deque
,生成器理解,等等。它不包含任何转换为列表或元组。
它甚至不需要同时获取所有数据,一次只能获取一个数据(生成器函数/理解也可以工作):避免无用的临时对象创建的优雅方法。
这要求iterable
仅在函数中迭代一次,这就是生成sorted
的{{1}}函数的情况。