2015-01-26 10 views

risposta

16

è necessario risolvere RDD e prendere elemento in mezzo o media di due elementi. Ecco ad esempio con 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

cos'è questo metodo di "ricerca"? AFAIK non esiste in RDD. – javadba

+0

@javadba yeah, è necessario importare SparkContext._ per portare implicazioni PairRDD nello scope –

+1

p.s. Penso che ci siano algoritmi più veloci per trovare la mediana che non richiede un ordinamento completo (http://en.wikipedia.org/wiki/Selection_algorithm) –

3

Utilizzando Spark 2.0 + e l'API dataframe è possibile utilizzare il metodo approxQuantile:

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

Si lavorerà anche su più colonne allo stesso tempo dal Spark versione 2.2. Impostando probabilites a Array(0.5) e relativeError a 0, verrà calcolata la mediana esatta. Da documentation:

La precisione di destinazione relativa da raggiungere (maggiore o uguale a 0). Se impostato su zero, vengono calcolati i quantili esatti, che potrebbero essere molto costosi.

Nonostante questo, sembra che ci sia qualche problema con la precisione quando si imposta relativeError-0, vedere la questione here. Un errore basso vicino a 0 in alcuni casi funzionerà meglio (dipenderà dalla versione di Spark).


Un piccolo esempio di lavoro che calcola la mediana dei numeri da 1 a 99 (entrambi inclusi) e utilizza un basso relativeError:

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

La mediana in risposta è 50,0.

Problemi correlati