我想按键分组RDD中的某些行,这样我就可以对一组内的行执行更高级的操作。请注意,我不想只计算一些总值。行是键值对,其中键是GUID,值是复杂对象。
根据pyspark文档,我首先尝试使用combineByKey实现它,因为它应该比groupByKey更高效。开头的列表仅用于说明,而不是我的真实数据:
l = list(range(1000))
numbers = sc.parallelize(l)
rdd = numbers.map(lambda x: (x % 5, x))
def f_init(initial_value):
return [initial_value]
def f_merge(current_merged, new_value):
if current_merged is None:
current_merged = []
return current_merged.append(new_value)
def f_combine(merged1, merged2):
if merged1 is None:
merged1 = []
if merged2 is None:
merged2 = []
return merged1 + merged2
combined_by_key = rdd.combineByKey(f_init, f_merge, f_combine)
c = combined_by_key.collectAsMap()
i = 0
for k, v in c.items():
if v is None:
print(i, k, 'value is None.')
else:
print(i, k, len(v))
i += 1
这个输出是:
0 0 0
1 1 0
2 2 0
3 3 0
4 4 0
这不是我的预期。使用groupByKey实现的相同逻辑返回正确的输出:
grouped_by_key = rdd.groupByKey()
d = grouped_by_key.collectAsMap()
i = 0
for k, v in d.items():
if v is None:
print(i, k, 'value is None.')
else:
print(i, k, len(v))
i += 1
返回:
0 0 200
1 1 200
2 2 200
3 3 200
4 4 200
因此,除非我遗漏了某些内容,否则当groupByKey优先于reduceByKey或combineByKey(相关讨论的主题:Is groupByKey ever preferred over reduceByKey)时就是这种情况。
答案 0 :(得分:0)
首选理解基本API时就是这种情况。特别是如果你检查list.append
docstring:
?list.append
## Docstring: L.append(object) -> None -- append object to end
## Type: method_descriptor
你会发现,就像Python API中的其他变异方法一样,它不会返回修改后的对象。这意味着f_merge
始终返回None
并且没有任何累积。
对于大多数问题,我们说的是比groupByKey
更有效的解决方案,但用combineByKey
(或aggregateByKey
)重写它绝不是其中之一。