pyspark combineByKey(而不是groupByKey)

时间:2016-06-19 12:03:03

标签: python apache-spark pyspark

我想按键分组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)时就是这种情况。

1 个答案:

答案 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)重写它绝不是其中之一。