site:enseignement:master:bdle:tmes:tme3-prise-main-spark
Différences
Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente | ||
site:enseignement:master:bdle:tmes:tme3-prise-main-spark [28/10/2016 17:40] – [Illustration du flatMap] hubert | site:enseignement:master:bdle:tmes:tme3-prise-main-spark [15/10/2018 09:09] (Version actuelle) – [Interrogation des données] amine | ||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
- | {{indexmenu_n> | + | {{indexmenu_n> |
- | ====== | + | ====== |
+ | |||
+ | **Remarque générale :** Le cours ne peut être // | ||
Pour l'aide sur l' | Pour l'aide sur l' | ||
- | |||
===== Exercice 1 ===== | ===== Exercice 1 ===== | ||
- | Commencer par copier et décompresser dans votre espace de travail le fichier | ||
- | |||
- | < | ||
- | |||
- | Le fichier obtenu, wordcount.txt (45Mo), contient des statistiques d’accès aux pages Wikimdia en différentes langue. | ||
- | Une ligne de la forme En.d updates 3 24145 indique dans une page écrite en anglais (symbole ‘En’), intitulée | ||
- | qui a été cliqué 3 fois et qui fait 24145 octets. | ||
+ | Copier le fichier | ||
+ | < | ||
Lancer le spark-shell en mode local ([[spark|voir Doc]]) en suivant les instructions fournies | Lancer le spark-shell en mode local ([[spark|voir Doc]]) en suivant les instructions fournies | ||
puis charger le fichier | puis charger le fichier | ||
Ligne 22: | Ligne 18: | ||
< | < | ||
- | Ici, la variable data est une RDD, et donc, de type Array tel que vous pouvez le constater sur le shell. | ||
- | L’invocation de la méthode take(n) sur cette variable affiche les n premiers éléments sur une seule ligne. Pour un affichage sur plusieurs lignes (tel un head -n sous linux), utiliser plutôt take(n).foreach(println) qui itère sur les éléments de la variable d’où elle est invoquée et affiche chaque élément sur une ligne séparément. | ||
- | Noter également que la méthode count retourne la cardinalité (nombre d’éléments) de la RDD d’où elle est invoquée. | ||
- | Par soucis de lisibilité de votre code, stocker le résultat de chaque question dans des variables nommées q1, q2, q3 etc. | ||
- | Penser à tester au fur et à mesure le résultat des instructions lorsque celles-ci ne contiennent que des transformations. | ||
- | |||
- | ==== Manipulation de RDDs Simples ==== | ||
- | |||
- | - Extraire le 4e champ de chaque élément de data et le convertir en type double | ||
- | - Construire à partir de q1 une liste contenant les nombres compris strictement entre 1000 et 1300 puis convertir en type entier. | ||
- | - Construire à partir de q2 une liste contenant les multiples de 3 et l’appeler q33. Faire de même pour les multiples de 4 et l’appeler q34. | ||
- | - Construire une liste obtenue en divisant par 10 chaque élément de q33. | ||
- | - Construire à partir de q4 un ensemble d’éléments (liste sans doublons).Construire une liste contenant les éléments de q2 qui sont multiples de 3 et de 4 à la fois. Utiliser impérativement q33 et q34. | ||
- | - Construire une liste contenant les éléments de q2 qui sont multiples de 3 mais pas de 4. Utiliser impérativement q33 et q34. | ||
- | - Construire à partir de q2 une liste contenant les éléments de q2 multiples de 3 ou de 10. Mettre les résultats dans la variable q8. | ||
- | - Convertir les éléments de q8 en type Double puis calculer la somme (q9sum), le minium (q9min) ainsi que le maximum (q9max) des éléments de q8. Calculer | ||
- | - Retourner pour chaque élément distinct de q2 le nombre de fois qu’il apparaît dans cette liste. | ||
==== Manipulation de RDDs sous forme de paires clé-valeur ==== | ==== Manipulation de RDDs sous forme de paires clé-valeur ==== | ||
Ligne 47: | Ligne 26: | ||
- Grouper les paires par ‘mot’ et additionner leur nombre nb. | - Grouper les paires par ‘mot’ et additionner leur nombre nb. | ||
- Reprendre les questions 3 et 4 en calculant ‘mot’ différemment : désormais, ‘mot’ doit correspondre au préfixe du premier sous-élément de chaque élément de list, çad, pour en.d, mot doit être en, pour fr.d, mot doit être fr, etc. Comparer les résultats avec ceux obtenus précédemment. | - Reprendre les questions 3 et 4 en calculant ‘mot’ différemment : désormais, ‘mot’ doit correspondre au préfixe du premier sous-élément de chaque élément de list, çad, pour en.d, mot doit être en, pour fr.d, mot doit être fr, etc. Comparer les résultats avec ceux obtenus précédemment. | ||
- | **Remarque** pour partitionner une chaîne de caractères en utilisant le point (.) comme délimiteur à l'aide de la méthode split(), il faut protéger le point avec \, i.e split(" | + | **Remarque** pour partitionner une chaîne de caractères en utilisant le point (.) comme délimiteur à l'aide de la méthode split(), il faut protéger le point avec \, i.e split(" |
+ | |||
+ | |||
+ | <showif isloggedin> | ||
+ | **Réponse** | ||
+ | <code scala> | ||
+ | // | ||
+ | |||
+ | val list = data.map(_.split(" | ||
+ | |||
+ | |||
+ | // | ||
+ | |||
+ | val q12 = list.map(x=> | ||
+ | |||
+ | // | ||
+ | |||
+ | val q13 = list.map(x=> | ||
+ | |||
+ | // | ||
+ | |||
+ | val q14 = q13.reduceByKey((x, | ||
+ | //ou bien q13.reduceByKey(_+_) | ||
+ | |||
+ | // | ||
+ | |||
+ | val q13bis = list.map(x=> | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | </ | ||
+ | </ | ||
===== Exercice 2 ===== | ===== Exercice 2 ===== | ||
Cet exercice s’intéresse à la formulation de jointures simples en Scala. | Cet exercice s’intéresse à la formulation de jointures simples en Scala. | ||
Ligne 72: | Ligne 84: | ||
* films (MovieID, Title, Genres) | * films (MovieID, Title, Genres) | ||
- | === Structure de donnée : Dataset=== | + | |
- | Pour le TME sur les Dataset, récupérer le fichier suivant: | + | |
- | <code bash> | + | |
- | cp / | + | |
- | emacs tme-dataset-etudiant.scala & | + | |
- | </ | + | |
Ligne 94: | Ligne 101: | ||
Par exemple, pour le nuplet (1,Toy Story (1995), | Par exemple, pour le nuplet (1,Toy Story (1995), | ||
Indice: pour construire films_bis, il est possible d’imbriquer une fonction map à l’intérieur d’une autre (cf. question 2 de l’exercice 3). | Indice: pour construire films_bis, il est possible d’imbriquer une fonction map à l’intérieur d’une autre (cf. question 2 de l’exercice 3). | ||
- | ===== Exercice subsidiaire ===== | ||
- | ==== Conversion d'un objet List en un objet Map ==== | + | |
- | Expliquer l' | + | <showif isloggedin> |
+ | **Réponse** | ||
<code scala> | <code scala> | ||
- | val x = List((" | + | //a. le nombre de notes (ratings) réalisées par chaque utilisateur identifié par son UserID |
+ | val q2a | ||
- | val x = List((22, " | + | //b. le nombre de notes (ratings) réalisées par chaque localisation donnée par le Zip-code |
+ | val q2b = utilis.map{case(userId, | ||
- | </ | ||
+ | //c. le nombre de notes (ratings) réalisées par chaque genre de film | ||
+ | //jointure en notes et films | ||
+ | val q2c = notes.map(x=> | ||
- | ==== Illustration du flatMap ==== | ||
- | Expliquer la différence entre les expressions | + | //d. les 10 utilisateurs ayant noté le plus de films. |
+ | val q2d = notes.map(x=> | ||
- | <code scala> | + | //e. Les films ayant reçu le moins de notes |
- | val x = List(1, 2, 3).map(x => List(x, 10*x, 100*x) | + | //f. Les utilisateurs n’ayant noté aucun film |
- | val x = List(1, 2, 3).flatMap(x => List(x, 10*x, 100*x)) | + | |
- | val y = List(List((1, | ||
- | val y = List(List((1, | ||
- | </ | ||
- | <code scala> | + | //genre de films |
- | | + | val films_bis |
- | </code> | + | |
- | Attention, le flatMap appliqué sur une Map retourne une Map. Pour garantir l' | ||
- | <code scala> | ||
- | val ys = Map(" | ||
</ | </ | ||
+ | </ | ||
- | La fonction passée en paramêtre au flatMap doit retourner une séquence. Ici une chaine de caractère est considérée implicitment comme une séquence de caractères. | ||
- | <code scala> | ||
- | val pers = Array( (1," | ||
- | val v = pers.flatMap(x=> | ||
- | val v = pers.flatMap{ case(numéro, | ||
- | </ | + | === Exercice Subsidiaire : reprendre les questions précédentes en utilisant l'API Dataset |
- | + | Pour utiliser les Dataset, récupérer | |
- | ==== Composition de Map ==== | + | <code bash> |
- | En considérant la variable pers de la question précédente, expliquer | + | cp / |
- | * pers.flatMap(x=>(x._2) map(y=> | + | emacs tme-dataset-etudiant.scala & |
- | * pers.flatMap(x=>(x._2) map(y=> | + | </code> |
- | * pers.flatMap(x=> | + | |
- | et expliquer pourquoi les deux instructions suivantes sont erronées | + | |
- | * pers.flatMap(x=>(x._1) map(y=> | + | |
- | * pers.flatMap(x=> | + | |
site/enseignement/master/bdle/tmes/tme3-prise-main-spark.1477669236.txt.gz · Dernière modification : de hubert