此page包含一些统计函数(mean,stdev,variance等),但不包含中位数。我怎样才能计算出精确的中位数?
由于
答案 0 :(得分:18)
您需要对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
答案 1 :(得分:4)
使用 Spark 2.0 + 和DataFrame 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。