web-dev-qa-db-fra.com

Comment fonctionnent les méthodes `map` et` reduction` dans les RDD Spark

Le code suivant provient du guide de démarrage rapide d’Apache Spark .. Quelqu'un peut-il m'expliquer en quoi consiste la variable "line" et d'où elle provient? 

textFile.map(line => line.split(" ").size).reduce((a, b) => if (a > b) a else b)

Aussi, comment une valeur est-elle passée dans a, b?

Lien vers le QSG http://spark.Apache.org/docs/latest/quick-start.html

14
DesirePRG

Tout d’abord, en fonction de votre lien, la textfile est créée en tant que

val textFile = sc.textFile("README.md")

tel que textfile est un RDD[String], ce qui signifie qu'il s'agit d'un ensemble de données réparti résilient de type String. L'API d'accès est très similaire à celle des collections Scala habituelles.

Alors maintenant, que fait cette map?

Imaginez que vous ayez une liste de Strings et que vous souhaitiez la convertir en une liste de Ints représentant la longueur de chaque chaîne.

val stringlist: List[String] = List("ab", "cde", "f")
val intlist: List[Int] = stringlist.map( x => x.length )

La méthode map attend une fonction. Une fonction qui va de String => Int. Avec cette fonction, chaque élément de la liste est transformé. Donc, la valeur de intlist est List( 2, 3, 1 )

Ici, nous avons créé une fonction anonyme à partir de String => Int. C'est x => x.length. On peut même écrire la fonction plus explicite comme 

stringlist.map( (x: String) => x.length )  

Si vous utilisez l'écriture explicite ci-dessus, vous pouvez

val stringLength : (String => Int) = {
  x => x.length
}
val intlist = stringlist.map( stringLength )

Donc, ici, il est absolument évident que stringLength est une fonction de String à Int.

Remarque : En général, map est ce qui constitue un soi-disant Functor. Pendant que vous fournissez une fonction de A => B, map du foncteur (ici Liste) vous permet d’utiliser cette fonction également à partir de List[A] => List[B]. Ceci s'appelle le levage.

Réponses à vos questions

Quelle est la variable "ligne"?

Comme mentionné ci-dessus, line est le paramètre d'entrée de la fonction line => line.split(" ").size

Plus explicite (line: String) => line.split(" ").size

Exemple: Si line est "hello world", la fonction renvoie 2.

"hello world" 
=> Array("hello", "world")  // split 
=> 2                        // size of Array

Comment une valeur est-elle passée dans a, b?

reduce attend également une fonction de (A, A) => A, où A est le type de votre RDD. Appelons cette fonction op.

Qu'est-ce que reduce. Exemple:

List( 1, 2, 3, 4 ).reduce( (x,y) => x + y )
Step 1 : op( 1, 2 ) will be the first evaluation. 
  Start with 1, 2, that is 
    x is 1  and  y is 2
Step 2:  op( op( 1, 2 ), 3 ) - take the next element 3
  Take the next element 3: 
    x is op(1,2) = 3   and y = 3
Step 3:  op( op( op( 1, 2 ), 3 ), 4) 
  Take the next element 4: 
    x is op(op(1,2), 3 ) = op( 3,3 ) = 6    and y is 4

Le résultat ici est la somme des éléments de la liste, 10.

Remarque : En général, reduce calcule

op( op( ... op(x_1, x_2) ..., x_{n-1}), x_n)

Exemple complet

Tout d’abord, textfile est un RDD [String], disons

TextFile
 "hello Tyth"
 "cool example, eh?"
 "goodbye"

TextFile.map(line => line.split(" ").size)
 2
 3
 1
TextFile.map(line => line.split(" ").size).reduce((a, b) => if (a > b) a else b)
 3
   Steps here, recall `(a, b) => if (a > b) a else b)`
   - op( op(2, 3), 1) evaluates to op(3, 1), since op(2, 3) = 3 
   - op( 3, 1 ) = 3
61
Martin Senne

Map et reduce sont des méthodes de la classe RDD, dont l'interface est similaire à celle des collections scala.

Ce que vous transmettez aux méthodes map et reduce est en fait une fonction anonyme (avec un paramètre dans la carte et deux paramètres dans une réduction). textFile appelle la fonction fournie pour chaque élément (ligne de texte dans ce contexte) dont il dispose.

Peut-être devriez-vous d'abord lire une introduction à la collection Scala.

Vous pouvez en savoir plus sur l'API de classe RDD ici: https://spark.Apache.org/docs/1.2.1/api/scala/#org.Apache.spark.rdd.RDD

6
Tyth

ce que map function fait, il prend la liste des arguments et la mappe à une fonction. Similaire à la fonction map en python, si vous êtes familier. 

En outre, le fichier est comme une liste de chaînes. (pas exactement mais c'est comme ça que ça se répète) 

Considérons que ceci est votre fichier. 

val list_a: List[String] = List("first line", "second line", "last line")

Voyons maintenant comment map function fonctionne. 

Nous avons besoin de deux choses, list of values que nous avons déjà et function à laquelle nous voulons mapper ces valeurs. considérons une fonction très simple pour comprendre. 

val myprint = (arg:String)=>println(arg)

cette fonction prend simplement un seul argument de chaîne et s'imprime sur la console. 

myprint("hello world")
hello world

si nous associons cette fonction à votre liste, ça va imprimer toutes les lignes

list_a.map(myprint)

Nous pouvons aussi écrire une fonction anonyme, comme mentionné ci-dessous, qui fait la même chose. 

list_a.map(arg=>println(arg))

dans votre cas, line est la première ligne du fichier. vous pouvez changer le nom de l'argument comme bon vous semble. par exemple, dans l'exemple ci-dessus, si je change arg en line cela fonctionnerait sans problème 

list_a.map(line=>println(line))
1
Gaurang Shah