[英]spark aggregatebykey - sum and running average in the same call
我正在學習火花,並且沒有使用hadoop的經驗。
問題
我正在嘗試在對AggregateByKey的同一調用中計算總和和平均值。
讓我分享到目前為止我所做的嘗試。
設置數據
val categoryPrices = List((1, 20), (1, 25), (1, 10), (1, 45))
val categoryPricesRdd = sc.parallelize(categoryPrices)
嘗試在對AggregateByKey的同一調用中計算平均值。 這是行不通的。
val zeroValue1 = (0, 0, 0.0) // (count, sum, average)
categoryPricesRdd.
aggregateByKey(zeroValue1)(
(tuple, prevPrice) => {
val newCount = tuple._1 + 1
val newSum = tuple._2 + prevPrice
val newAverage = newSum/newCount
(newCount, newSum, newAverage)
},
(tuple1, tuple2) => {
val newCount1 = tuple1._1 + tuple2._1
val newSum1 = tuple1._2 + tuple2._2
// TRYING TO CALCULATE THE RUNNING AVERAGE HERE
val newAverage1 = ((tuple1._2 * tuple1._1) + (tuple2._2 * tuple2._1))/(tuple1._1 + tuple2._1)
(newCount1, newSum1, newAverage1)
}
).
collect.
foreach(println)
結果:每次打印不同的平均值
只需先求和,然后在單獨的操作中計算平均值。 這可行。
val zeroValue2 = (0, 0) // (count, sum, average)
categoryPricesRdd.
aggregateByKey(zeroValue2)(
(tuple, prevPrice) => {
val newCount = tuple._1 + 1
val newSum = tuple._2 + prevPrice
(newCount, newSum)
},
(tuple1, tuple2) => {
val newCount1 = tuple1._1 + tuple2._1
val newSum1 = tuple1._2 + tuple2._2
(newCount1, newSum1)
}
).
map(rec => {
val category = rec._1
val count = rec._2._1
val sum = rec._2._2
(category, count, sum, sum/count)
}).
collect.
foreach(println)
每次都打印相同的結果:(1,4,100,25)
我想我了解seqOp和CombOp之間的區別。 鑒於操作可以在不同服務器上的多個分區之間拆分數據,我的理解是seqOp對單個分區中的數據進行操作,然后combOp合並從不同分區接收的數據。 如果這是錯誤的,請更正。
但是,有一些我不太了解的基本知識。 看起來我們無法在同一調用中同時計算總和和平均值。 如果是這樣,請幫助我理解原因。
與seqOp
的average
聚合有關的計算:
val newAverage = newSum/newCount
並在combOp
:
val newAverage1 = ((tuple1._2 * tuple1._1) + (tuple2._2 * tuple2._1)) / (tuple1._1 + tuple2._1)
是不正確的。
假設前三個元素在一個分區中,最后一個元素在另一個分區中。 您的seqOp
將生成(計數,總和,平均值)元組,如下所示:
Partition #1: [20, 25, 10]
--> (1, 20, 20/1)
--> (2, 45, 45/2)
--> (3, 55, 55/3)
Partition #2: [45]
--> (1, 45, 45/1)
接下來,跨分區combOp
將合並兩個分區中的2個元組,得到:
((55 * 3) + (45 * 1)) / 4
// Result: 52
從上述步驟可以看到,如果RDD元素的順序或分區不同,則average
可能會不同。
您的第二種方法有效,因為按定義, average
是總和超過總計數,因此在先計算總和和計數值之后可以更好地進行計算。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.