Python 如何使用reduceByKey而不是GroupByKey来构造列表?

Python 如何使用reduceByKey而不是GroupByKey来构造列表?,python,apache-spark,pyspark,rdd,Python,Apache Spark,Pyspark,Rdd,我的RDD由许多项组成,每个项都是一个元组,如下所示: (key1, (val1_key1, val2_key1)) (key2, (val1_key2, val2_key2)) (key1, (val1_again_key1, val2_again_key1)) ... and so on 我在RDD上使用了GroupByKey,结果如下 (key1, [(val1_key1, val2_key1), (val1_again_key1, val2_again_key1), (), ... (

我的RDD由许多项组成,每个项都是一个元组,如下所示:

(key1, (val1_key1, val2_key1))
(key2, (val1_key2, val2_key2))
(key1, (val1_again_key1, val2_again_key1))
... and so on
我在RDD上使用了GroupByKey,结果如下

(key1, [(val1_key1, val2_key1), (val1_again_key1, val2_again_key1), (), ... ()])
(key2, [(val1_key2, val2_key2), (), () ... ())])
... and so on
我需要用reduceByKey做同样的事情。我试过了

RDD.reduceByKey(lambda val1, val2: list(val1).append(val2))
但它不起作用

请建议使用reduceByKey()实现的正确方法答案是你不能(或者至少不能以一种不滥用语言动态性的直截了当的方式)。由于值类型和返回类型不同(元组列表与单个元组)
reduce
在这里不是有效的函数。您可以使用
combineByKey
aggregateebykey
例如:

rdd = sc.parallelize([
    ("key1", ("val1_key1", "val2_key1")),
    ("key2", ("val1_key2", "val2_key2"))])

rdd.aggregateByKey([], lambda acc, x: acc + [x], lambda acc1, acc2: acc1 + acc2)

但它只是
groupByKey
的一个效率较低的版本。另请参见

这应该可以工作……但它是以列表开始的,所以我认为您只需要删除列表包装器……
val1.append(val2)
@JustinPihony我刚刚尝试了这个方法,但它抛出了“AttributeError:'tuple'对象没有属性'append'”,可能是因为第一个元素开始工作时不是一个列表a)您不能(以非黑客的方式)因为左侧和右侧的类型不匹配,所以请执行相同的操作。b) 它的效率显著降低,因为它不会减少任何东西。看啊,我不太了解我的python类型……我以为你已经有了一个列表。在这种情况下,使用aggregateByKey不会阻止密钥在网络中被洗牌吗?这意味着该函数将针对其所在节点上的任何键运行,而不必担心其他节点上是否存在键。@Salmonard实际上,我已经查看了PySpark代码,它还没有禁用映射端聚合。因此,这相当于
groupByKey
。总的来说,还有另一个问题。如果每个分区的唯一键数较低,则执行映射端聚合可能是有益的。但一般来说,由于它必须创建大量临时对象,因此成本很高。这是一个缓慢的过程,这些对象必须在以后进行垃圾收集。感谢您的进一步澄清。您知道使用Scala版本是否会比pySpark有任何性能提升,或者提供更好的解决方案吗?我期待任何精彩的事情。虽然可以稍微快一点,但大部分作业可能是序列化、传输和序列化。