Python pyspark中的reduce和count结果不同
对于我的spark试用版,我下载了,并将它们合并到一个文件nytaix.csv中。然后我将其保存在hadoop fs中。我正在使用7个节点管理器的spark on纱线 我正在连接spark over Ipython笔记本电脑 下面是一个示例python脚本,用于计算nytaix.csv中的行数Python pyspark中的reduce和count结果不同,python,hadoop,apache-spark,Python,Hadoop,Apache Spark,对于我的spark试用版,我下载了,并将它们合并到一个文件nytaix.csv中。然后我将其保存在hadoop fs中。我正在使用7个节点管理器的spark on纱线 我正在连接spark over Ipython笔记本电脑 下面是一个示例python脚本,用于计算nytaix.csv中的行数 nytaxi=sc.textFile("hdfs://bigdata6:8020/user/baris/nytaxi/nytaxi.csv") filtered=nytaxi.filter(lambda
nytaxi=sc.textFile("hdfs://bigdata6:8020/user/baris/nytaxi/nytaxi.csv")
filtered=nytaxi.filter(lambda x:"distance" not in x)
splits = filtered.map(lambda x: float(x.split(",")[9]))
splits.cache()
splits.count()
返回73491693。
但是,当我尝试用下面的代码计算行数时,它返回一个大约803000的值
def plusOne (sum, v):
#print sum, v
return sum + 1;
splits.reduce(plusOne)
我想知道为什么结果不同。
谢谢
csv中的示例行:
u'740BD5BE61840BE4FE3905CC3EBE37E,E48B185060FB0FF49BE6DA43E69E624B,CMT,1,N,2013-10-01 12:44:292013-10-01 12:53:26,1536,1.20,-73.974319,40.741859,-73.99115,40.742424' 因为我无法对我的发现发表评论,所以我将它们写在这里 我可以用一个更简单的例子来重现你的问题
data = xrange(1, 10000)
len(data) #output => 9999
xrangeRDD = sc.parallelize(data, 8)
print xrangeRDD.count()
def plusOne (v,sum):
#print sum, v
return v + 1;
a = xrangeRDD.reduce(plusOne)
print a
输出
9999
1256
9999
2502
9999
9999
对于xrangeRDD=sc.parallelize(数据,4)
输出
9999
1256
9999
2502
9999
9999
对于xrangeRDD=sc.parallelize(数据,1)
输出
9999
1256
9999
2502
9999
9999
因为我只是改变了分区的数量,也就是改变了reduce的输出,所以我认为reduce只提供了一个分区的输出,正如这里的模式所建议的那样
我还在学习spark是如何工作的。因此,我无法完全理解为什么会发生这种情况。我希望通过这些额外的细节,有人能够解释这背后的原因 这不是完整的答案 因为我无法对我的发现发表评论,所以我将它们写在这里 我可以用一个更简单的例子来重现你的问题
data = xrange(1, 10000)
len(data) #output => 9999
xrangeRDD = sc.parallelize(data, 8)
print xrangeRDD.count()
def plusOne (v,sum):
#print sum, v
return v + 1;
a = xrangeRDD.reduce(plusOne)
print a
输出
9999
1256
9999
2502
9999
9999
对于xrangeRDD=sc.parallelize(数据,4)
输出
9999
1256
9999
2502
9999
9999
对于xrangeRDD=sc.parallelize(数据,1)
输出
9999
1256
9999
2502
9999
9999
因为我只是改变了分区的数量,也就是改变了reduce的输出,所以我认为reduce只提供了一个分区的输出,正如这里的模式所建议的那样
我还在学习spark是如何工作的。因此,我无法完全理解为什么会发生这种情况。我希望通过这些额外的细节,有人能够解释这背后的原因 的文档说明:
使用指定的交换和关联二进制运算符减少此RDD的元素
def plusOne(sum,v):返回sum+1
不可交换。它完全忽略其中一个参数。因此,您看到的是未定义的行为。(我建议您考虑一下为什么函数必须是可交换的。如果您理解这一点,那么您对Spark的理解会更好一些!)
解决方案是使用RDD.count()
。但如果您坚持使用reduce()
,您会这样做:
def count(rdd):
return rdd.map(lambda x: 1).reduce(lambda a, b: a + b)
文件说明:
使用指定的交换和关联二进制运算符减少此RDD的元素
def plusOne(sum,v):返回sum+1
不可交换。它完全忽略其中一个参数。因此,您看到的是未定义的行为。(我建议您考虑一下为什么函数必须是可交换的。如果您理解这一点,那么您对Spark的理解会更好一些!)
解决方案是使用RDD.count()
。但如果您坚持使用reduce()
,您会这样做:
def count(rdd):
return rdd.map(lambda x: 1).reduce(lambda a, b: a + b)
问题在于
reduce
中使用的操作必须是关联的和可交换的:
请注意,在每个分区上完成的reduce
是对其迭代器reduceLeft
的简单委托。这不会造成任何问题,因为这只是价值的积累
val mergeResult = (index: Int, taskResult: Option[T]) => {
if (taskResult.isDefined) {
jobResult = jobResult match {
case Some(value) => Some(f(value, taskResult.get))
case None => taskResult
}
}
}
但是,分区的合并是一个问题。下面是在您的示例中它将如何分解(假设在4个均匀分割的分区上有40个计数):
因此,您应该更喜欢count
,或者按照Daniel的建议和map
,或者您有第三个选项来进行聚合
rdd.aggregate(0)(_+1, _+_)
这将使用0作为计数种子,在本地将1添加到累加器中,然后在合并中将两个累加器添加到一起。问题在于
reduce
中使用的操作必须是关联的和可交换的:
请注意,在每个分区上完成的reduce
是对其迭代器reduceLeft
的简单委托。这不会造成任何问题,因为这只是价值的积累
val mergeResult = (index: Int, taskResult: Option[T]) => {
if (taskResult.isDefined) {
jobResult = jobResult match {
case Some(value) => Some(f(value, taskResult.get))
case None => taskResult
}
}
}
但是,分区的合并是一个问题。下面是在您的示例中它将如何分解(假设在4个均匀分割的分区上有40个计数):
因此,您应该更喜欢count
,或者按照Daniel的建议和map
,或者您有第三个选项来进行聚合
rdd.aggregate(0)(_+1, _+_)
这将使用0作为计数的种子,在本地将1添加到累加器,然后在合并中将两个累加器添加到一起。您能提供您正在使用的csv文件的某些部分吗?在问题文本中添加了一个示例行。据我所知,您得到的输出仅对应于一个分区,而不是整个RDD。我能够重现这个问题,如果没有分区被减少到1,那么输出count和reduce匹配。我仍在学习spark,所以不确定为什么会发生这种情况。您能提供您正在使用的csv文件的某些部分吗?在问题文本中添加了一行示例。据我所知,您得到的输出仅对应于一个分区,而不是整个RDD。我能够重现这个问题,如果没有分区被减少到1,那么输出count和reduce匹配。我还在学习spark,所以不知道为什么会发生这种情况。