理论上,我认为我理解aggregate
的工作方式,但我无法通过一个非常简单的例子。
值得注意的是,示例here似乎有错误的结果。当我在我的机器上运行以下示例时,我得到.....
seqOp = (lambda x, y: (x[0] + y, x[1] + 1))
combOp = (lambda x, y: (x[0] + y[0], x[1] + y[1]))
ag = sc.parallelize([1, 2, 3, 4]).aggregate((1,0), seqOp, combOp)
然后,我得到的结果是
>>> ag
(12, 4)
但是,我引用的链接说结果是(19, 4)
。这家伙正在使用不同版本的spark (1.2.0)
。我正在使用1.5.2.
聚合函数是否在Spark版本之间发生了变化?
如果答案是 NO ,那么12
如何成为该元组中的第一个元素仍然令人困惑。只检查元组的第一个元素,我们可以看到
对于RDD中的每个元素,y
被添加到元组的第一个元素中。
因此,从(1,0)开始,由于y
分别为1, 2, 3, 4,
,这应该会产生一系列元组,如:(2,1), (3,1), (4,1), (5,1)
。现在,当我添加元组系列中的第一个元素时,我得到14
?对于如何获得12
,我有什么明显的遗漏吗?非常感谢。
答案 0 :(得分:1)
不,aggregate
功能的行为没有改变。
链接示例的问题是零元素不是中性的。因为在实践中,每个分区创建一次零值,您实际上可以通过增加分区数量并且根本不传递任何数据来增加元组的第一个元素:
sc.parallelize([], 10).aggregate((1,0), seqOp, combOp)
## (11, 0)
sc.parallelize([], 100).aggregate((1,0), seqOp, combOp)
## (101, 0)
asc.parallelize([], 1000).aggregate((1,0), seqOp, combOp)
## (1001, 0)
这里的消息是,在你执行的操作中零值应该是中性的。
修改强>:
中性元素是什么意思?在代数意义上它应该identity element seqOp
/ combOp
。我在这里定义的操作案例是一个很好的选择(0, 0)
。
从开发人员的角度来看,您可以认为zeroElement
添加到您的数据中的次数不是合同的一部分。