web-dev-qa-db-fra.com

Utilisation de ReduceByKey dans Apache Spark (Scala)

J'ai une liste de Tuples de type: (identifiant utilisateur, nom, nombre).

Par exemple,

val x = sc.parallelize(List(
    ("a", "b", 1),
    ("a", "b", 1),
    ("c", "b", 1),
    ("a", "d", 1))
)

J'essaie de réduire cette collection à un type où chaque nom d'élément est compté.

Donc, ci-dessus, val x est converti en:

(a,ArrayBuffer((d,1), (b,2)))
(c,ArrayBuffer((b,1)))

Voici le code que j'utilise actuellement:

val byKey = x.map({case (id,uri,count) => (id,uri)->count})

val grouped = byKey.groupByKey
val count = grouped.map{case ((id,uri),count) => ((id),(uri,count.sum))}
val grouped2: org.Apache.spark.rdd.RDD[(String, Seq[(String, Int)])] = count.groupByKey

grouped2.foreach(println)

J'essaie d'utiliser ReduceByKey car il fonctionne plus rapidement que groupByKey.

Comment peut-on réduire la réduction de la clé au lieu du code ci-dessus pour fournir la même correspondance?

22
blue-sky

En suivant votre code:

val byKey = x.map({case (id,uri,count) => (id,uri)->count})

Vous pourriez faire:

val reducedByKey = byKey.reduceByKey(_ + _)

scala> reducedByKey.collect.foreach(println)
((a,d),1)
((a,b),2)
((c,b),1)

PairRDDFunctions[K,V].reduceByKey Prend une fonction de réduction associative qui peut être appliquée au type V du RDD [(K, V)]. En d'autres termes, vous avez besoin d'une fonction f[V](e1:V, e2:V) : V. Dans ce cas particulier avec somme sur Ints: (x:Int, y:Int) => x+y Ou _ + _ En notation de soulignement courte.

Pour mémoire: reduceByKey fonctionne mieux que groupByKey car il tente d'appliquer localement la fonction de réduction avant la phase de shuffle/réduire. groupByKey forcera un mélange de tous les éléments avant le regroupement.

28
maasg

Votre structure de données d'origine est: RDD [(String, String, Int)] et reduceByKey ne peut être utilisé que si la structure de données est RDD [(K, V)].

val kv = x.map(e => e._1 -> e._2 -> e._3) // kv is RDD[((String, String), Int)]
val reduced = kv.reduceByKey(_ + _)       // reduced is RDD[((String, String), Int)]
val kv2 = reduced.map(e => e._1._1 -> (e._1._2 -> e._2)) // kv2 is RDD[(String, (String, Int))]
val grouped = kv2.groupByKey()            // grouped is RDD[(String, Iterable[(String, Int)])]
grouped.foreach(println)
5
cloud

La syntaxe est ci-dessous:

reduceByKey(func: Function2[V, V, V]): JavaPairRDD[K, V],

qui dit que pour la même clé dans un RDD, il prend les valeurs (qui seront certainement du même type) effectue l'opération fournie dans le cadre de la fonction et renvoie la valeur du même type que celle du RDD parent.

0
napster