Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache spark pyspark折叠法输出_Apache Spark_Pyspark - Fatal编程技术网

Apache spark pyspark折叠法输出

Apache spark pyspark折叠法输出,apache-spark,pyspark,Apache Spark,Pyspark,我对fold的输出感到惊讶,我无法想象它在做什么 我希望something.fold(0,lambda,b:a+1)将返回something中的元素数,因为fold从0开始,并为每个元素添加1 sc.parallelize([1,25,8,4,2]).fold(0,lambda a,b:a+1 ) 8 我来自Scala,fold的工作方式与我描述的一样。那么,折叠在pyspark中应该如何工作呢?谢谢你的想法 为了理解这里发生了什么,让我们看看Spark的折叠操作的定义。因为您使用的是PySp

我对
fold
的输出感到惊讶,我无法想象它在做什么

我希望
something.fold(0,lambda,b:a+1)
将返回
something
中的元素数,因为fold从
0开始,并为每个元素添加
1

sc.parallelize([1,25,8,4,2]).fold(0,lambda a,b:a+1 )
8

我来自Scala,fold的工作方式与我描述的一样。那么,折叠在pyspark中应该如何工作呢?谢谢你的想法

为了理解这里发生了什么,让我们看看Spark的
折叠操作的定义。因为您使用的是PySpark,所以我将展示代码的Python版本,但是Scala版本展示了完全相同的行为(您也可以):

(有关比较,请参阅)

Spark的折叠操作是先折叠每个分区,然后折叠结果。问题是一个空分区被折叠到零元素,因此最终的驱动程序端折叠结果是每个分区折叠一个值,而不是每个非空分区折叠一个值。这意味着
折叠的结果对分区的数量敏感:

>>> sc.parallelize([1,25,8,4,2], 100).fold(0,lambda a,b:a+1 )
100
>>> sc.parallelize([1,25,8,4,2], 50).fold(0,lambda a,b:a+1 )
50
>>> sc.parallelize([1,25,8,4,2], 1).fold(0,lambda a,b:a+1 )
1
在最后一种情况下,发生的是单个分区被向下折叠到正确的值,然后该值与驱动程序处的零值一起折叠,得到1

似乎Spark的
fold()
操作实际上要求fold函数除了关联函数外还具有可交换性。实际上,Spark中还有其他地方强加了这一要求,例如,在一个无序分区中,元素的顺序在不同的运行中可能是不确定的(请参阅)


我打开了一张Spark JIRA票来调查这个问题:。

让我试着给出一些简单的例子来解释Spark的折叠方法。我将在这里使用pyspark

rdd1=sc.parallelize(列表([]),1)

上面这一行将创建一个带有一个分区的空rdd

rdd1.折叠(10,λx,y:x+y)

这使产量达到20%

rdd2=sc.parallelize(列表([1,2,3,4,5]),2)

上面这一行将创建值为1到5的rdd,总共有2个分区

rdd2.折叠(10,λx,y:x+y)

这将产生45%的输出

为了简单起见,在上面的例子中,这里发生的是,第0个元素是10。因此,RDD中所有数字的和现在加上10(即第0个元素+所有其他元素=>10+1+2+3+4+5=25)。现在我们还有两个分区(即分区数*第零个元素=>2*10=20) fold发射的最终输出为25+20=45

使用类似的过程,可以清楚地了解为什么rdd1上的折叠操作会产生20作为输出

当我们有空列表时,Reduce失败,比如
rdd1.Reduce(lambda x,y:x+y)

ValueError:无法减少()空RDD

如果我们认为rdd中可以有空列表,则可以使用Fold
rdd1.折叠(0,λx,y:x+y)

正如预期的那样,这将产生0的输出


感谢彻底的回答,我忽略了分区如何影响折叠。因此,为了澄清Scala的情况,RDD分区与Scala的典型折叠行为产生了重要的差异。也就是说,
List(1,2,3,4).fold(0)((a,b)=>a+1)
将与Spark的
sc.parallelize(List(1,2,3,4)).fold(0)((a,b)=>a+1)
@keegan,是的,没错:分区行为,加上排序不确定性的某些来源,这意味着当您使用非交换运算符时,Spark折叠的行为当前将不会像您预期的那样。为了进一步说明这一点,请尝试以下操作:在Scala中,
Seq(2.0,3.0)。fold(1.0)((a,b)=>pow(b,a))
将始终返回9.0。在Spark中尝试同样的方法:
sc.parallelize(Seq(2.0,3.0),2)。折叠(1.0)((a,b)=>pow(b,a))
。在我的多核笔记本电脑上,Spark版本将不确定地返回8.0或9.0,这取决于哪个分区首先完成。
>>> sc.parallelize([1,25,8,4,2], 100).fold(0,lambda a,b:a+1 )
100
>>> sc.parallelize([1,25,8,4,2], 50).fold(0,lambda a,b:a+1 )
50
>>> sc.parallelize([1,25,8,4,2], 1).fold(0,lambda a,b:a+1 )
1