[英]How to calculate the mean of each pair in an RDD consisting of (Key, [Value]) pairs in Spark?
我對Scala和Spark都很新,所以請原諒我,如果我正在解決這個錯誤的錯誤。 在獲取csv文件,過濾和映射之后; 我有一個RDD,它是一堆(String,Double)對。
(b2aff711,-0.00510)
(ae095138,0.20321)
(etc.)
當我在RDD上使用.groupByKey()時,
val grouped = rdd1.groupByKey()
獲得一堆(String,[Double])對的RDD。 (我不知道CompactBuffer的意思,也許可能導致我的問題?)
(32540b03,CompactBuffer(-0.00699, 0.256023))
(a93dec11,CompactBuffer(0.00624))
(32cc6532,CompactBuffer(0.02337, -0.05223, -0.03591))
(etc.)
一旦他們被分組,我試圖取平均值和標准差。 我想簡單地使用.mean()和.sampleStdev()。 當我嘗試創建一個新的RDD的手段,
val mean = grouped.mean()
返回錯誤
錯誤:(51,22)value mean不是org.apache.spark.rdd.RDD [(String,Iterable [Double])]的成員
val mean = grouped.mean()
我導入了org.apache.spark.SparkContext._
我也嘗試使用sampleStdev(),. sum(),. stats(),結果相同。 無論出現什么問題,它似乎都會影響所有數字RDD操作。
我們考慮以下幾點:
val data = List(("32540b03",-0.00699), ("a93dec11",0.00624),
("32cc6532",0.02337) , ("32540b03",0.256023),
("32cc6532",-0.03591),("32cc6532",-0.03591))
val rdd = sc.parallelize(data.toSeq).groupByKey().sortByKey()
計算每對平均值的一種方法如下:
您需要定義一個平均方法:
def average[T]( ts: Iterable[T] )( implicit num: Numeric[T] ) = {
num.toDouble( ts.sum ) / ts.size
}
您可以在rdd上應用您的方法,如下所示:
val avgs = rdd.map(x => (x._1, average(x._2)))
你可以查看:
avgs.take(3)
這就是結果:
res4: Array[(String, Double)] = Array((32540b03,0.1245165), (32cc6532,-0.016149999999999998), (a93dec11,0.00624))
reduceByKey
方式是使用reduceByKey
而不是groupByKey
。
val result = sc.parallelize(data)
.map { case (key, value) => (key, (value, 1)) }
.reduceByKey { case ((value1, count1), (value2, count2))
=> (value1 + value2, count1 + count2)}
.mapValues {case (value, count) => value.toDouble / count.toDouble}
另一方面,解決方案中的問題是將表單對象的RDD grouped
(String, Iterable[Double])
(就像在錯誤中一樣)。 例如,您可以計算Ints或double的RDD的平均值,但是對的rdd的平均值是多少。
這是一個沒有自定義功能的完整程序:
val conf = new SparkConf().setAppName("means").setMaster("local[*]")
val sc = new SparkContext(conf)
val data = List(("Lily", 23), ("Lily", 50),
("Tom", 66), ("Tom", 21), ("Tom", 69),
("Max", 11), ("Max", 24))
val RDD = sc.parallelize(data)
val counts = RDD.map(item => (item._1, (1, item._2.toDouble)) )
val countSums = counts.reduceByKey((x, y) => (x._1 + y._1, x._2 + y._2) )
val keyMeans = countSums.mapValues(avgCount => avgCount._2 / avgCount._1)
for ((key, mean) <- keyMeans.collect()) println(key + " " + mean)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.