2015-01-26 282 views

回答

16

你需要理清RDD并采取元素中的两个元素的中间或平均。这是例如用RDD [INT]:

import org.apache.spark.SparkContext._ 

    val rdd: RDD[Int] = ??? 

    val sorted = rdd.sortBy(identity).zipWithIndex().map { 
    case (v, idx) => (idx, v) 
    } 

    val count = sorted.count() 

    val median: Double = if (count % 2 == 0) { 
    val l = count/2 - 1 
    val r = l + 1 
    (sorted.lookup(l).head + sorted.lookup(r).head).toDouble/2 
    } else sorted.lookup(count/2).head.toDouble 
+0

这是什么“查找”方法? AFAIK它不存在于RDD中。 – javadba 2015-01-28 10:21:06

+0

@javadba是的,你需要导入SparkContext._带来PairRDD暗示范围 – 2015-01-28 14:21:27

+1

p.s.我认为有更快的算法找到不需要完整排序的中位数(http://en.wikipedia.org/wiki/Selection_algorithm) – 2015-05-20 17:45:34

3

使用星火2.0+和数据帧API,你可以使用approxQuantile方法:

def approxQuantile(col: String, probabilities: Array[Double], relativeError: Double) 

它也将在多个列,因为同时工作Spark版本2.2。通过将probabilites设置为Array(0.5)relativeError为0,它将计算确切的中值。从documentation

实现的相对目标精度(大于或等于0)。如果设置为零,则计算确切的分位数,这可能非常昂贵。

尽管如此,当将relativeError设置为0时,似乎存在一些精度问题,请参阅问题here。接近于0的低错误在某些情况下会更好地工作(取决于Spark版本)。


一个小工作示例,其计算的数字从1到99(包括两个端值)的中值,并使用低relativeError

val df = (0 to 99).toDF("num") 
val median = df.stat.approxQuantile("num", Array(0.5), 0.001)(0) 
println(median) 

平均返回是50.0。