2016-05-15 5 views
0

Wenn ich ein Datensatz wie folgt aus:Pair RDD Transformations

val list = List ((1,1), (1,2), (1,3), (2,2), (2,1), (3,1), (3,3))

Und ich möchte per-Taste, um den Durchschnitt zu finden, damit der Ausgang sein sollte:

(1, 2), (2, 3/2), (3, 2) kann ich dies tun mit groupByKey, countByKey, and reduceByKey irgendwie oder muss ich combineByKey-Methode ähnlich dem unten gezeigten Beispiel verwenden: Ich versuchte mit groupByKey, countByKey, and reduceByKey, aber diese Kombination von Methoden nicht funktionieren, fragte ich mich, ob jemand einen Weg kennt, es mit diesen drei Methoden zu tun?

val result = input.combineByKey(
(v) => (v, 1), 
(acc: (Int, Int), v) => (acc._1 + v, acc._2 + 1), 
(acc1: (Int, Int), acc2: (Int, Int)) => (acc1._1 + acc2._1, acc1._2 + acc2._2)). 
map{ case (key, value) => (key, value._1/value._2.toFloat) } 

result.collectAsMap().map(println(_)) 

Antwort

4

sollten Sie versuchen, die folgenden:

val sc: SparkContext = ... 
val input = sc.parallelize(List((1,1), (1,2), (1,3), (2,2), (2,1), (3,1), (3,3))) 
val averages = input.groupByKey.map { case (key, values) => 
    (key, values.sum/values.size.toDouble) 
} 

println(averages.collect().toList) // List((1,2.0), (2,1.5), (3,2.0)) 
+0

Oh Recht habe ich vergessen, wenn Sie groupByKey es die Werte in einem Array setzt, so dass Sie Summe und Größe verwenden können auf diesem Array! Danke für die Hilfe! – CapturedTree

1

Nun, Sie einfach PairRDDFunctions.groupByKey verwenden können und berechnen, was Sie wollen.

val avgKey = input.groupByKey.map{ 
    case (k, v) => (k, v.sum.toDouble/v.size) 
} 
avgkey.collect 
//res2: Array[(Int, Double)] = Array((3,2.0), (1,2.0), (2,1.5)) 
1

Mit reduceByKey mit vorheriger Transformation der duples in Drillinge,

rdd.map{ case(k,v) => (k,(v,1)) }. 
    reduceByKey((a,v) => (a._1+v._1, a._2+v._2)). 
    map {case (k,v) => (k, v._1/v._2)} 
+0

Hallo Ulme! Entschuldigung für die späte Antwort, aber können Sie bitte erklären, wann Sie 'case' in einer Kartenfunktion verwenden würden? Ist es nur so, dass Sie die Parameter als '(k, v)' schreiben können, anstatt spezifisch angeben zu müssen, wie 'k' und' v' strukturiert sind. Wenn zum Beispiel "k" ein Tupel wäre, würde ich ohne den Fall in der Map schreiben müssen "((a1, a2), v)'? Also ist es technisch nur für den Mustervergleich? – CapturedTree

+0

Mit 'case' ermöglichen wir * Mustererkennung, zum Extrahieren oder Zerlegen von Datenstrukturen, und wir verwenden geschweifte Klammern, um eine Teilfunktion zu definieren (nicht alle Muster müssen definiert werden). Auf der anderen Seite beinhaltet die Verwendung einer Tupel-Datenstruktur die Verwendung ihrer eigenen Methoden (._1 und ._2), um die Datenelemente zu erhalten (extrahieren). – elm

Verwandte Themen