试图理解reduceByKey()动作的行为

时间:2017-10-01 13:25:20

标签: python apache-spark

我只是想找到与特定键相关的所有值的平均值,以下是我的程序:

from pyspark import SparkContext,SparkConf

conf = SparkConf().setAppName("averages").setMaster("local")
sc = SparkContext(conf=conf)

file_rdd = sc.textFile("C:\spark_programs\python programs\input")

vals_rdd = file_rdd.map(lambda x:(x.split(" ")[0],int(x.split(" ")[2])))

print type(vals_rdd)

pairs_rdd = vals_rdd.reduceByKey(lambda x,y:(x+y)/2)

for line in pairs_rdd.collect():
    print line

以下是输入数据:

a hyd 2
b hyd 2
c blr 3
d chn 4
b hyd 5

当我运行程序时,我得到的输出如下:

(u'a', 2)
(u'c', 3)
(u'b', 3) -- I could see only got b's value getting averaged.
(u'd', 4)

除了b值之外,所有值都没有被平均。为什么会这样?为什么没有a,c,d值平均值?

1 个答案:

答案 0 :(得分:1)

reduceByKey is used to

  

使用关联和可交换 reduce函数合并每个键的值。

您通过的功能并不满足这些要求。特别是它不是关联的:

f = lambda x,y:(x + y) / 2

f(1, f(2, 3))
## 1.75
f(f(1, 2), 3)
## 2.25

因此,它不适用于您的情况,也不会对这些值进行平均。

  

值不是平均值。为什么会这样?

除了上面解释的基本缺陷外,每个剩余密钥只有一个值,因此根本没有理由调用合并功能。

  

我只是想找到与特定键相关联的平均值

只需使用DataFrames

vals_rdd.toDF().groupBy("_1").avg()

虽然你可以use aggregateByKey with StatCounter(数值稳定)或map -> reduceByKey -> map(数值不稳定)。

此外,我强烈建议您阅读reduceByKey: How does it work internally?的优秀答案。