我想与Python共享这个特定的Apache Spark解决方案,因为它的文档非常糟糕。
我想通过KEY计算K/V对(存储在成对RDD中)的平均值。以下是示例数据的外观:
>>> rdd1.take(10) # Show a small sample.
[(u'2013-10-09', 7.60117302052786),
(u'2013-10-10', 9.322709163346612),
(u'2013-10-10', 28.264462809917358),
(u'2013-10-07', 9.664429530201343),
(u'2013-10-07', 12.461538461538463),
(u'2013-10-09', 20.76923076923077),
(u'2013-10-08', 11.842105263157894),
(u'2013-10-13', 32.32514177693762),
(u'2013-10-13', 26.249999999999996),
(u'2013-10-13', 10.693069306930692)]
现在,下面的代码序列是一种不太理想的方法,但它确实有效。在我找到更好的解决方案之前,我就是这么做的。这并不可怕,但是——正如你将在回答部分看到的那样——有一种更简洁、更有效的方法。
>>> import operator
>>> countsByKey = sc.broadcast(rdd1.countByKey()) # SAMPLE OUTPUT of countsByKey.value: {u'2013-09-09': 215, u'2013-09-08': 69, ... snip ...}
>>> rdd1 = rdd1.reduceByKey(operator.add) # Calculate the numerators (i.e. the SUMs).
>>> rdd1 = rdd1.map(lambda x: (x[0], x[1]/countsByKey.value[x[0]])) # Divide each SUM by it's denominator (i.e. COUNT)
>>> print(rdd1.collect())
[(u'2013-10-09', 11.235365503035176),
(u'2013-10-07', 23.39500642456595),
... snip ...
]
现在,更好的方法是使用
rdd.aggregateByKey()
方法。因为这个方法在Apache Spark和Python文档中的文档记录太少了--这也是我编写这个Q&A的原因--直到最近我一直在使用上面的代码序列。但同样,它的效率较低,因此除非有必要,否则请避免这样做。下面介绍如何使用
rdd.aggregateByKey()
方法(推荐的)执行相同的操作。。。按键,同时计算和(我们要计算的平均值的分子)和计数(我们要计算的平均值的分母):
上面每对
a
和b
的含义如下所示(这样您就可以看到发生了什么):最后,计算每个键的平均值,并收集结果。
我希望这个用
aggregateByKey()
回答的问题会有帮助。只是添加了一个关于这个问题的直观和简短(但不好)的解决方案的注释。书Sam's Teach Yourself Apache Spark in 24 Hours已经在最后一章很好地解释了这个问题。
使用
groupByKey
可以像这样轻松地解决问题:输出:
这是直观和吸引人的,但不要使用它!
groupByKey
不在映射器上进行任何组合,并将所有单独的键值对带到还原器。尽量避免
groupByKey
。使用类似于@pat的reduceByKey
解决方案在我看来,一个更具可读性的等价物是带有两个lambdas的aggregateByKey:
这样,整个平均值计算将是:
相关问题 更多 >
编程相关推荐