BDE Et Spark Cours 11

Télécharger au format pdf ou txt
Télécharger au format pdf ou txt
Vous êtes sur la page 1sur 98

Data Engineering et Spark avec Scala

2022-2023
A propos de Moi

2020-Present: Big Data Engineer @ Atos Sénégal


• Aider les métiers sur le développement des KPI’s.
• Chargement de données dans le Datalake
• Mettre à la disposition des data scientists, des données aggrégées.
2019-2020: Big Data Engineer @ MNS Consulting
• Installation d’un environnnement Big Data et Mis en place d’une
plateforme d’analyse et de prise de décision, se basant sur les
données mobile.
• Mis en place de plateforme de visualisation des données provenant
des capteurs IOT’s.
2017-2019: Ibrahima FALL
Lead Big Data Engineer @ Atos Senegal,
• Msc en Big Data, AIMS Mbour Email: [email protected]
• Msc en Algèbre appliquée Cryptographie, Université de Thiés Alt-email: [email protected]
Le rôle de Data Engineer et la
plateforme Big Data
Vue 360 des services et utilisations sur une plateforme Big Data

2022-2023
Sommaire
1. Le Big Data et L’Ecosystème Hadoop

2. Les différentes types de plateforme


1. Les plateformes On Premise
2. Les plateformes sur le Cloud

3. La plateforme Hortonworks
1. Ambari et les différents services
2. L’accès local SSH aux serveurs et services sur les nœuds du cluster
3. Les commandes HDFS

4. La plateforme Databricks
Le Big Data et L’Ecosystème Hadoop
 L’ère de la donnée en grande quantité
 A chaque instant, nous produisons de la donnée :

 Un avion en vole génère environ 10 Terabytes de données chaque 30min

 Facebook ingère chaque jour plus de 500 Terabytes de nouvelles données dans
ses bases de données.

 Le désigne de vastes ensembles de données


collectées, pouvant être explorées et analysées afin d’en dégager
des informations exploitables

 Les Systèmes de traitement traditionnel n’étant plus adapté pour le


traitement des grandes quantités de données, quel environnement pour
assurer ce dernier ?
Rapid Growth
Data Lifecycle
de données pour l’entreprise.

What is a ’

BDE and its


roles ’

Assurer la supervision des systèmes pour vérifier qu’ils s’exécutent


correctement et qu’ils sont économiques.
What is
BDE and
its roles
Tools Used








Le Big Data et L’Ecosystème Hadoop
 L’ecosystéme Hadoop

 Une architecture bien précise est définie ( )
 Les services qu’embarquent les sont installés sur les
nœuds du Cluster

 Exemple de Framework

 Exemple d’architecture
 Type StandAlone
 Type Master - Slave - Edge

 Pas d’architecture fixe (architecture évolutive)
 Les ressources sont extensibles
 Concept de Big Data as a Service (BDaaS)

 Exemple de Big Data Cloud Providers
Plateforme de test

1. En local (terminal)
(https://github.com/KhalilFall/Introduc
tion-to-
spark_Data221/blob/main/Installation_
apache_spark_windows_linux_Mac.md)
2. IntelliJ (plugin Scala)
3. Sur le cloud (Databricks)
Introduction à Spark avec Scala
Vue 360 des services et utilisations sur une plateforme Big Data

2022-2023
Sommaire

1. Règles de base 1. Introduction à Spark


2. Les variables 1. Définition
2. Initialisation de Spark
3. Manipulation des String 1. Les options de Spark-shell
2. SparkContext
4. Les Opérateurs
2. RDD & DataSet / DataFrame
5. Les Collections
3. Operations sur les RDD
6. Les Structures de contrôle
4. Operations sur les DataFrame
7. Les Fonctions 5. Lecture et Ecriture
8. La Programmation Orienté Objet 6. Déploiement Job Spark
Scala : C’est quoi– Pourquoi?
 Un langage de programmation

 Développé en 2001 par à l'École Polytechnique Fédérale de Lausanne (EPFL) en suisse en 2001
 Première version publique sortie fin 2003

 Scalabe (d’où son nom Scala)

 Tiré du Java avec une Syntaxe assez simple

 Scala combine

(basée sur des fonctions. Ex : val a = List (1,2).
En réalité List() est un fonction qui derrière, combine des
Iterable, Seq…etc Mais l’utilisateur ne voit que la fonction simple)

 Scala est Dynamiquement typé (Ex: val a = 2 , renvoie un Int)

 …etc.
Règles de base
 Le caractère ‘;’ en fin d’instruction est optionnel sauf si plusieurs instructions sur une ligne

 Sensible à la casse

 Le nom des classes débute par une majuscule

 Les methodes commencent par un minuscule

 Le nom du fichier du programme doit correspondre au nom de l’objet en question

 La fonction def main(args: Array[String]) est obligatoire et représente le point d’entré du programme

 Les noms de variables, d’objets, de classes, de fonctions débutent par une lettre ou un underscore. Ex: nom, _nom, _1_nom

 Commentaires:
• // => une ligne
• /* … */ => multiple lignes

 Import de modules:
• import org.me._ => importe toutes les méthodes dans me
• import org.me.porterHabit => n’importe que la méthode porterHabit
• import org.me.{seLaver, porterHabit} => n’importe que les méthodes porterHabit et seLaver
Les DataTypes
 Syntaxe Générale
nomVaribale [ : DataType] = valeur

 Les valeurs de keywords peuvent être:


 val : Pour designer une variable immuable (dont le contenu est non modifiable après
assignation)

 var : Pour désigner une variable mutable (dont le contenu est modifiable après assignation)

 lazy val: Pour designer une variable qui n’est évaluée que lorsqu’elle est appelée

Exemple : var maProfession = ’’data engineer’’

 On peut déclarer plusieurs Variables en même temps:


Exemple 1 : val (a,b,c) = (1,2,3) # a, b, c valent 1,2,3
Exemple 2 : val a,b = 100 # a et b valent 100
 Créer une variable mutable nommée « profession » et renseigner la
valeur : Data Engineer

 Vous avez été muté et vous êtes maintenant « scrum master ». Changer
votre profession.

 Créer en une seule commande les variable nom, prenom et age. Pour des
raisons de fraudes sur l’identité de la personnes, personne ne doit
pouvoir modifier les valeurs de ces variables.

 Afficher les variables à l’aide de la fonction println(" ")

println(s" Mon age est $age")


println(" Et mon nom complet est %s %s".format(nom, prenom))
val proverb: String = "apprendre à positiver ses emotions pour etre en harmonie avec soi-meme et avec les autres"

• proverb(0)  L’élément à l’indice 0


• proverb.length  renvoie la taille de la chaine
• proverb.capitalize  renvoie la première lettre en Majuscule
• proverb. toUpperCase  renvoie la chaine en Majuscule
• proverb.substring(0,9)  renvoie les 9 premiers caractères
• proverb.contains('e')  renvoie True si la chaine contient 'e'
• proverb.count(lettre => lettre =='e')  renvoie le nombre d’occurrence de 'e'
• proverb.replace("e", "a")  remplace tous les 'e' par 'a‘
• proverb.concat("Une autre phrase")  rajoute "Une autre phrase« à proverb
• proverb.filter(lettre => lettre !='e')  Supprime tous les 'e‘ de proverbe
 (0 to 10).contains(10)
 (0 until 10).contains(10)
 "foo".drop(1)
 "bar".take(2)
 Créer une variable noel avec le contenu suivant: "Petit papa Noël Quand
tu descendras du ciel Avec des jouets par milliers N’oublie pas mon petit soulier.
Mais avant de partir Il faudra bien te couvrir Dehors tu vas avoir si froid
C’est un peu a cause de moi."
 Créer la variable nbPhrase, contenant le nombre de phrase dans noel
 Créer la variable nbA, contenant le nombre d'occurence de 'a' dans noel
 Découper le texte en phrase et metter le dans la variable phrasesNoel
 Récupérer la dernière phrase de phraseNoel dans la variable lastPhrase
 Afficher le contenu de lastPhrase avec un effet mirroir c'est à dire de la fin au début.
 Opérateurs arithmétiques
• +, -, *, /, % correspondant respectivement à l’addition , la soustraction, la multiplication, la division
et le modulo

 Opérateurs de comparaison
• ==  égalité
• !=  différent
• >, >=  strictement supérieur et supérieur ou égal
• <, <=  strictement inférieur et inférieur ou égal

 Opérateurs logiques
• &&  ET logique
• ||  OU logique
• !  NOT

 Opérateurs d’affectation
• =, +=, -=, *=, /=, %=
1. Combien de temps (en Jours et en Heure) il faut à un marcheur pour parcourir une distance de 750km à une vitesse de
4.8km/h
• : Vitesse = Distance/Temps et la fonction println() permet d’afficher un résultat

2. Un magicien dit que


• Quand on choisit un nombre premier différent de 2 et 3
• On l’èleve au carré
• On lui ajoute 17
• On divise par 12
• Alors le reste de la division vaut 6 ?

3. Le gouvernement a décidé d'offrir une prime de 300€ à certains fonctionnaires en fonction de leur salaire et de leur ancienneté.
Comme toutes les autres mesures prises par le gouvernement, il est difficile de comprendre à qui cette mesure s'applique.
De ce que vous avez compris, une personne peut toucher à la prime si :
Critère 1 : Elle a de d'ancienneté son salaire est à euros.
Critère 2 : Elle a d'ancienneté son salaire est compris euros.
Critère 3 : Elle a de d'ancienneté son salaire est strictement à euros à euros. C'est à
dire qu'une personne ayant plus de 10 ans d'ancienneté et un salaire entre 1500 et 2300 euros ne peut pas toucher à cette prime.

Bernadette a ans d'ancienneté et un salaire de euros.


Marc a ans d'ancienneté et un salaire de euros.
 Les Tableaux (ou Array)
 Syntaxe :

 En initialisant la taille du tableau


val tab = new Array[DataType](longueur)

 En précisant les valeurs par défaut


val tab2 [:Array[T]] = Array(value1, value2…., valueN)

Exemple :
val tab = new Array[Int](3)
val tab2 : Array[Int] = Array(2,2,3)

NB : Les array sont mutables


 Les Tableaux (ou Array)
 Ajout de valeurs (avant – après) :
 Array.concat, ++, :+, :+
val v1 = Array(4,5,6)

 val v2 = v1 7 // Array(4, 5, 6, 7)

 val v3 = v2 Array(8,9) // Array(4, 5, 6, 7, 8, 9)

 val v4 = 3 v3 // Array(3, 4, 5, 6, 7, 8, 9)

 val v5 = Array(1,2) v4 // Array(1, 2, 3, 4, 5, 6, 7, 8, 9)


 Les Tableaux (ou Array)
 Quelques fonctions natives :

val nums = Array(1,2,3) // oubien (1 to 3).toArray

 nums.map(_ * 2) // Array(2, 4, 6)

 nums.filter(element => element < 3) // Array(2)

 nums.indexOf(2) // 1

 nums.size // 3

 num.mkString("-") // "1-2-3"
1. Créer un tableau nommé

2. On s’est rendu compte tardivement que les « Poissons » ne sont


pas des fruits: Supprimer le du tableau.(NB: Les Array sont
immuables)
3. Rajouter à la liste de fruits suivante à ‘ ’ : [‘Orange’,
‘Papaye’]
4. Quelle est la nouvelle taille de ‘ ’
5. A quelle index se trouve la ‘Mangue’ ?
 Les Listes
 Syntaxe :

 val maListe: [List[T]] = List(element1, element2,… elementN)

 Val maListe = element1 :: element2 :: ….. :: ElementN :: Nil

 val maListe = List()

Exemple :
val maListe : List[String] = List("a", "b", "c", "d", "a")

NB : Les sont immutables


 Les Listes
 Ajout de valeurs (avant – après) :

val x = List(1,2,3)

 val y = 0 :: x ou 0 +: x //List(0, 1, 2, 3)

 val z = y ::: List(4,5) // List(0, 1, 2, 3, 4, 5)

 val l = List.concat(y, List(4,5)) // List(0, 1, 2, 3, 4, 5)

 val l2 = y :+ 5 // List(0, 1, 2, 3, 4, 5)
 Les Listes
 Quelques fonctions natives :

val maListe: List[String] = List("a", "b", "c", "d", "a", "z")

• maList.slice(0, 2)  List("a", "b")


• maList.takeRight(1) z
• maList.filter(x => x !=b)  List("a", "c", "d", "a")
• "q" +: maList :+ "l"  List("q","a", "b", "c", "d", "a", "z", "l")
• maList.contains("b")  true
• maList.length 6
• maList.count(x => x =="a") 2
• maList.reverse  List(z, a, d, c, b, a)
• maList.mkString("-")  "a-b-c-d-a-z"
1. Soit la liste suivante : ["pomme", "banane", "goyave", "banane", "kaki", "pomplemousse"]
1. Créer la liste et stockée la dans une variable « Fruits »

2. Afficher le 3e élément de la liste


3. Ajouter les fruits « ananas » et « pastèque » respectivement au début et à la fin de la liste Fruits
et stocker la nouvelle liste dans une liste « Fruits_1 » en une ligne de commande
4. Quelle est la nouvelle taille de « Fruits_1 »
5. Vérifier que « goyave » fait partit de « Fruits_1 »
6. Compter le nombre de fois que « banane » apparait dans « Fruits_1 »
7. Dans une variable « Fruits_sorted », trier les fruits de « Fruits_1 »
8. Supprimer tous les fruits de « Fruits_sorted » dont la taille dépasse 5 caractères et stocker le
résultat dans une variable « Fruits_small »
9. Afficher « Fruits_small »
 Les Set
 Syntaxe :

 val maSet: [Set[T]] = Set(element1, element2,… elementN)

Exemple :
val maSet : Set[Int] = Set(1, 8, 4, 9)

NB :
 Les Set ne contiennent pas de doublons
 Les Set
 Ajout et suppression:

val maSet = Set(1,2,3)

 val y = maSet + 0 //Set(1, 2, 3, 0)

 val z = y ++ Set(4,5) // Set(0, 1, 2, 3, 4, 5)

 val l = z - 2 // Set(0, 1, 3, 4, 5)

 val l2 = l -- Set(1, 2, 3, 0) // Set(0, 1, 3)


 Les Set
 Quelques fonctions natives :

val maSet1 : Set[Int] = Set(1, 8, 4, 9)


val maSet2 : Set[Int] = Set(1, 8, 5, 0, 12)

• maSet1.mkString ("-")  "1-8-4-9"


• maSet1.take(1)  Set(1)
• maSet1.contains(4)  true
• maSet1.apply(10)  false
• maSet1.intersect(maSet2)  Set(1, 8)
• maSet1.diff(maSet2)  Set(4, 9)
• maSet1.drop(1)  Set(8, 4, 9)
• maSet1.filter(_ > 4)  Set(8, 9)
 Créer un Set contenant les éléments "I","am","trained","to
be", "a", "data", "engineer"
 Récupérer les éléments contenant la lettre "a"
 En utilisant map, transforme le Set en une collection
contenant la taille des éléments de l'ensemble.
 filtrer les valeurs paires
 Calculer la somme total de cet ensemble d'entiers
 Les Tuples
 Syntaxe :

 val maTup : TupleX[T1, T2, …] = TupleX(el1, el2, …)

Exemple :
val maTup : Tuple3[String,String,Int]=Tuple3("dia", "mor", 28)
 Les Tuples
 Quelques fonctions natives :

val maTup : Tuple3[String,String,Int]=Tuple3("dia", "mor", 28)


• maTup._1  "dia"
• maTup._3  28
• maTup. productElement(2)  "mor"
• maTup. productArity 3
 Créer un Tuple "moi" contenant votre prenom, nom, taille,
sexe
 Accéder à votre taille
 Renvoyer la phase suivante: Je suis prenom nom, j'ai une
taille de taille et de sexe sexe.
 Les Map
 Syntaxe :

 val maMap: Map[K, V] = Map(k1 -> v1, k2 -> v2, …)

Exemple :
val maMap : Map[String, String] = Map("nom"-> "dia", "prenom"->"mor", "age"->"28")
 Les Map
 Quelques fonctions natives :

val maMap: Map[String, String] = Map("nom"-> "dia", "prenom"->"mor", "age"->"28")


• maMap.keys  Set(nom, prenom, age)
• maMap.values  MapLike(dia, mor, 28)
• maMap.getOrElse("sex", "Key unknown !")  " Key unknown !") "
• maMap +("sex" -> "M")  Map("nom"-> "dia", "prenom"-
>"mor", "age"->"28")
• maMap.filter(_._1 == "age")  Map(age -> 28)
• maList.size 4
 Créer le dictionnaire weekDay conntenant les valeurs suivantes : 1=>lundi, 2=>mardi,
3=>mercredi, 4=>jeudi, 5=>vendredi, 6=>samedi, 7=>dimanche

 Recupérer les clefs de weekDay dans une variable weekDayKeys

 Convertir weekDayKeys en liste dans une variable weekDayKeys1

 Filtrer les éléments de weekDayKeys1 qui sont pairs dans une variable weekDayKeys2

 Pour chaque élément de weekDay, afficher la phrase 'La clef ... a pour valeur ...‘

 Récupérer les valeurrs de weekDay dans une variable weekDayVals

 Afficher avec println 'Les jours de la semaine sont Lundi, Mardi, Mercredi, Jeudi,
Vendredi, Samedi, Dimanche.'
 Pour travailler avec des collections muables, il faut importer la collection à partir du
package scala.collection.mutable (https://www.scala-lang.org/api/2.13.6/scala/collection/mutable/index.html)

 Exemple: importons la classe ArrayBuffer et utiliser la dans les questions ci-dessous



 En initialisant un tableau vide

 En précisant les valeurs par défaut

1. Soit le tableau suivant : ["pomme", "banane", , "viande", "goyave", "orange", "kaki", "pomplemousse"]

1. Créer la liste et stockée la dans un ArrayBuffer « fruitsMuables »

2. Ajouter les fruits "ananas" et « pastèque » respectivement au début et à la fin de la liste Fruits en utilisant
la fonction append et prepend

3. Supprimer l'élément "viande" en utilisant la fonction remove.


 –

• Syntaxe générale :

if (1==2){
print(“true”)
}else {
print(“False”)
}

 Syntaxe générale :  Syntaxe avec filtre :


( itt <- collection) { itt <- collection if cond1 if cond2 …} {
//code //code
} }

: :
for( i <- 1 to 10) { for( i <- 1 to 10 if i%2==0) {
println(i) println(i)
} }

 Syntaxe générale :

( expression booléenne) {
// code
}

:
var i = 1
while( i <=10) {
println(i)
i+=1
}

 Syntaxe générale :

do {
// code
} ( expression booléenne)

:
var i = 1
do {
println(i)
i+=1
} while( i <=10)

 :

nomVar {
case exp1 => instruction1
case exp2 => instruction2

case _ => instruction par défaut
}

:
var age = 18
age match {
case 18 => println("Vous avez 18 ans.")
case x if (x < 18) => println("Vous avez moins de 18 ans.")
case 19 | 20 => println("Vous avez 19 ou 20 ans.")
case _ => println("Vous avais plus de 20 ans")
}
1. Importer scala.io.StdIn.readInt, puis demander à l'utilisateur de saisir son age dans une variable « mon_age ».
 Vérifier si vous êtes un enfant, un adolescent un adulte ou un papi. En sachant que :
 0 < enfant <= 9
 10 <= adolescent<= 18
 18 < adulte <= 60
 Papi > 60
NB: Utiliser premièrement puis
2. Vérifier les parmi les années 1900 jusqu’à 2030, lesquels sont Bissextiles
 Tips :
 Une année est bissextile si elle est divisible par 4 et non par 100 à moins que l’année soit divisible par
400
3. Écrire un programme de dévinette en utilisantla fonction suivante

 Forcer l'utilisateur à saisir un nombre compris entre 0 et 100.


 Générer un nombre aléatoire avec la fonction
 Dites à l'utilisateur s'il a saisit un nombre supérieur, inférieur ou égal au nombre généré par la fonction
 Continuer à demander à l'utilisateur de saisir jusqu'à ce qu'il saisit le nombre généré.


• un input renvoie toujours la même sortie
• elle n'a pas de d'effet de bord, c'est à dire qu'elle se contente juste de retourner une
valeur. En d'autres termes elle contient pas de variables mutables, ni de i/o operations, ni
de variables non local ...

• elle peut être affectée à une variable
• elle peut être considérée comme argument d'une autre fonction
• elle peut être retournée par une autre fonction

NB: Toutes les fonctions sont de première classe dans Scala.

• prend une ou plusieurs fonctions en arguments


• retourne une fonction comme output
 Syntaxe générale de création d’une fonction

 def nomFonction ([args: DataType]): TypeRetour = {


//… code
[return] result
}

def nomFunction[A, B, C](args1: A, args2:C, …): : TypeRetour = {


//… code
result
}

:
 def sum(x: Int, y: Int) : Int = {
val result = x + y
result
}
 def sum(x: Int, y: Int) : Int = x + y
 def lasElement[T](l: List[T]): T = l.head
 Créer une fonction qui calcule le nombre d'éléments paires dans une liste, tester avec List(3, 12, 16, 32, 54, 5, 23,
87, 98, 52, 99, 24).

 Ecrire une fonction qui prend en entrée un nombre quelconque n et renvoie une liste des nombres d'Amstrong qui
sont entre 1 et n.
 Un nombre est Amstrong si le nombre à la puissance sa longueur est egale à lui même
 : 100 => 1 + 0 + 0 != 100 donc 100 n'est pas un nombre Amstrong.

 : 20 => 2 + 0 != 20 donc 200 n'est pas un nombre Amstrong.

 : 371 => 3 + 7 + 1 = 371 d'ou 371 est un nombre amstrong

 Créer une fonction qui vérifie si 2 mots sont anagrammes


 Deux mots S1 et S2 sont anagrammes si toutes les lettres se trouvant dans S1 sont dans S2 et leurs tailles sont égales
(penser à mettre les mots en minuscule)
 Tester le code sur les mots suivants :
 Admise / Samedi Avenir / Navire
 Balise / Blaise Cancer / Cancre
 Centre / Récent Cigare / Cirage
 Direct / Crédit Dragee / Gardee / Gradee
 Équipe / Piquée Égerie / Érigée
 Entite / Teinte / Tetine Gerard / Regard / Garder
 Granit / Gratin Limace / Malice
 Ménage / manège Orange / Organe
• Écrire une fonction générique filterDuplicates, qui enlève les doublons d'un tableau
quelconque.

• Ecrivez une fonction qui prend en entrée une chaine de caractère et un caractère puis
supprime le caractère spécifié dans la chaine. Si le caractère spécifié ne fait pas partie de la
chaîne, celle-ci devra être retournée intacte. Par exemple :
• purge("Bonjour","o") renverra "Bnjur"
• purge("J'ai horreur des espaces"," ") renverra "J'aihorreurdesespaces"
• purge("Moi, je m'en fous", "y") renverra "Moi, je m'en fous"

• Réécrire la fonction précédente en spécifaint le nombre caractère à supprimer


 Syntaxe générale de création d’une fonction

 Val nomFunction = (args: DataType) => transformation …

 Exemple: val division = (x: Int, y: Int) => x / y; division(1, 2)

Exercices:
• Ecriver 3 fonctions anonymes qui doivent faire l'addition, la
soustraction et la multiplications de 2 nombres entiers puis metter
les dans 3 variables addition, soustraction, multiplication
• Ecriver une fonction d'ordre supérieur operation qui prend en
entrée 2 entiers et une fonction f (f est une fonction qui prend en
entrée 2 entiers et renvoie un entier) et qui renvoie la resultante de f
appliquée au 2 premiers arguments i.e f(x,y).
• Utiliser la fonction operation pour calculer 77+33, 6x7, 24-8
Introduction to Spark
Introduction à Spark

 Apache Spark est un système de traitement distribué open


source utilisé pour les traitements de données à grande échelle.

 Utilise, pour des requêtes rapides sur des données de toute


taille, des processus comme :
 :Traitement et Stockage des données
intermédiaires en utilisant la mémoire (écriture en Mémoire plus rapide
que l’écriture en Disk)
 : Mécanisme de re-Distribution/ re-Partition des données lors
des opérations.
Introduction à Spark

Introduction à Spark

Introduction à Spark

Introduction à Spark

 Spark avec
 Scala =>
 Python =>

 Les Options
 --name NAME :name = nom de l’application
 --master TYPE :type = yarn, local, mesos…etc.
 --driver-memory MEM :mem = Driver memory (default 1G)
 --num-executors NUM :num = nombre d’executeurs à l’exécution
 --executor-memory MEM :mem = executor memory (default 1G)
 --executor-cores NUM :num = nombre de cores par executeur
Introduction à Spark

 Point d’entrée principal d’une exécution Spark (Main)

 A l’initialisation d’une Session (ex: spark-shell), l’objet SparkSession est


disponible comme avec le nom
 Mais peut être réinitialisé :

import org.apache.spark.sql.SparkSession
val spark:SparkSession = SparkSession.builder()
.master("yarn")
.appName("mon application")
.getOrCreate()
RDD

 Resilient Distributed Dataset, sont des « collections » d’éléments


partitionnées et distribuées à travers les nœuds du cluster

 C’est la structure fondamentale de base dans Spark

 Les RDD permettent d’effectuer des opérations parallèles en


mémoire sur un cluster.

 Quelques caractéristiques
 Traitement en mémoire
 Lazy evalution
 Immuables
 …

 Il existe deux (2) manières de créer un RDD


 A partir d’une
( )

Exemple:
val fruits= Seq((1,"orange" ),(2,"pomme"),(3,"fraise"),(4,"citron"))
val fruitRDD = spark.sparkContext.parallelize(fruits )

 A partir d’une
("cheminVersFichier")
 Créer une variable à partir de la collection partagée dans
codeshare
 Créer la variable contenant la variable définie
précédemment avec le syntaxe
( )
 En utilisant la fonction count, donner le nombre total
d'enregistrements(commandes) contenus dans .
 En utilisant distinct, donner le nombre dinctinct de commandes
effectués.
 Afficher les 5 premiers éléments de avec la fonction take(5)

 De manière générale, les rdds supportent 2 types d’opérations:


A partir d’un RDD, retourne un autre RDD après un traitement

 map(func)
 filter(func)
 flatMap(func)
 groupByKey(([numPartitions])
 reduceByKey(func, [numPartitions])
 sortByKey([ascending], [numPartitions])
 join(otherDataset, [numPartitions ])
 coalesce(numPartitions)
 repartition(numPartitions)

https://spark.apache.org/docs/latest/rdd-programming-guide.html#transformations

 De manière générale, les rdds supportent 2 types


d’opérations:


A partir d’un RDD retourne une valeur
 (func)
 ()
 ()
 ()
 ()
 (func)

https://spark.apache.org/docs/latest/rdd-programming-guide.html#actions
 Sélectionner des colonnes
 Pour un RDD de String avec un delimiteur d=, ou ; ou | ou …

rdd1.map(line => line.split("d")(position de la colonne))

NB: Penser à transfomer votre RDD initial en RDD de collection plus facile à traiter

 Pour un RDD de collection

rdd1.map(line => line(position de la colonne))

Exercices:
En utilisant rdd1,
• Créer une variable contenant les valeurs contenues dans category
• Créer une seconde variable contenant les valeurs de nom_client et sex
• Afficher les 5 premiers lignes de ces variables
 Renommer ou faire des opérations sur une colonne
 Transformer une colonne

rdd1.map(line => tranformation(line))

NB: transformation est une fonction quelconque qui peut s'appliquer sur line.

Exercices:
• Créer une variable contenant un RDD des années des différents commandes.
• Créer une fonction qui prend en entrée une chaine au format 'yyyy-MM-
dd' puis renvoie 'yyyy'
• Créer une variable , puis en utilisant la fonction pour ajouter une
nouvelle information dans rdd1
• Créer une fonction qui prend en entrée un argument de type Any
et un argument de type Any également puis renvoie si value est null sinon
renvoie value
• Créer une variables qui va se baser sur et remplace les valeurs
null de la colonne (pos 5) par 0.
 Appliquer des filtres en utilisant filter

rdd1.filter(line => condition(line))

NB: condition est une fonction qui renvoie toujours un bouléen.

Exercices:
• Afficher et compter les personnes qui ont commmandé 1 seul produit.
• Afficher et compter les personnes qui ont commandé des bananes.
• Afficher et compter les personnes qui ont commander des produits coutant plus de
50.
 Aggrégations
 Les fonctions pouvant être utilisées:

groupByKey, countByValue, countByValue, reduceByKey

Exercices:
• Déterminer le nombre total de commandes par date. Pour cela, il faut transformer le
rdd initial et récupérer que le couple date et quantite, après appliquer un
reduceByKey
• Afficher la quantité totale commander par produit et par client.
 Repartitionner un dataframe

 Affichons le nombre de partitions de df.


rdd1.getNumPartitions

 Diminuons le nombre de partitions avec coalesce()

rdd1.coalesce(n)

 Augmentons le nombre de partitions avec repartition()

rdd2.repartition(n)











DataFrame

 Est une collections distribuées de données

 Est organisé en colonnes nommées. Il est équivalent à une


table dans une base de données relationnelle.

Lecture et Ecriture de
plusieurs formats de
données autorisées

 Il existe plusieurs manières de créer un DataFrame

 A partir d’une

 A partir d’un

 A partir d’une s

 A partir d’un RDD



val plats = Seq(("Thieb djeune", "2000"), ("Mafe", "3000"), ("Soupou kandja", "3500"))

val plats_rdd = spark.sparkContext.parallelize(plats)

val plats_dataframe = plats_rdd.toDF("Menu", "Prix")


plats_dataframe.show(false)

NB : La methode show() prend 2 arguments optionnelles :


 Truncate : true | false Affiche les lignes du dataframe sans être tronquée
 Nb_row : Int Le nombre de ligne du dataframe à afficher

 ’

val plats_list = List(("Thieb djeune", "2000"), ("Mafe", "3000"), ("Soupou kandja", "3500"))

val plats_dataframe = plats_list .toDF("Menu", "Prix")

val plats_list = List(("Thieb djeune", "2000"), ("Mafe", "3000"), ("Soupou kandja", "3500"))

val plats_dataframe = spark.createDataFrame(plats_list).toDF("Menu", "Prix")


 A partir d’une source externe









 ….

 Création en à partir d’une table en utilisant


spark.sql("select * from ingestion.personne_tmp")
 Créons un exemple de Dataframe grâce à la collection partagée que nous nommerons
.
 Afficher les informations contenues dans df

df.show(nbLignes, false/true)

 Voir le schéma d'un dataFrame

df.printSchema

 Voir les Statistiques

df.summary()
 Sélectionner des colonnes
 select avec les noms de colonnes en String

df.select("colonne1", "colonne2", …)

 select avec la fonction col

df.select(col("colonne1"), col("colonne2"), …)

 selectExpr

df.selectExpr("colonne1", "colonne2", …)

Exercices:(https://spark.apache.org/docs/latest/api/java/org/apache/spark/sql/functions.html )
• Afficher, à partir de , les colonnes et (en le mettant en
majuscule avec la fonction ).
 Renommer ou faire des opérations sur une colonne
 Renommer

df.withColumnRenamed("oldCol", "newCol")

 Ajouter une nouvelle colonne

df.withColumn("newColonne", opérations)

 Transformer une colonne

df.withColumn("colonne1", opérations)

Exercices:
• Renommer la colonne en .
• Remplacer le contenu de la colonne prix par le prix réel c’est-à-dire le produit des
colonnes quantité et prix puis afficher.
• Créer une nouvelle colonne qui est la résultante du produit des colonnes
et .
 Appliquer des filtres en utilisant filter ou where
 En mode Sql

df.where("colonne1 != 0")

 En mode DataFrame

df.where(col("colonne1") =!= 0")

Exercices:
• Afficher les personnes qui on fait 1 seul produit.
• Afficher les personnes qui ont commander de la banane. (Avec les 2 méthodes)
• Afficher les personnes qui ont commander des produits coutant plus de 50.
 Nettoyage des valeurs Null
 na.fill

df.na.fill("0", Seq("colonner1", "colonne2", …)

 na.drop

df.drop(Seq("colonne1", "colonne2"))

 na.replace

df.na.replace(Seq("colonne1"), Map("v1"->"v11", "v2"->"v22"))

Exercices:
• Remplacer les valeurs null de la colonne quantite par 1.
• Remplacer les valeurs h par 1 et f par 0.
 When - otherwise

df.withColumn("col1", when(conditon, opération).otherwise(opération))

Exercices:
• Créer une colonne libelle_sex, qui résulte de la colonne sex en convertissant les
valeurs h par homme et f par femme.
 Aggrégations
 Syntaxe:

df.groupBy("col1", "col2", …).agg(sum(""), count(""), ….)[.orderBy("c")]

Exercices:
• Déterminer le nombre total de commandes par date.
• Afficher la quantité totale commander par produit et par client puis trier par quantité
totale.
• Afficher le nombre de produit total et le nombre de produit distinct par client.
 Les types de jointures
 Les types de jointures

Exercices:

• Créons une nouveau datframe df2 avec la collection 2.


Seq(("Moussa", 16, "Senegal"),("Fatou", 16, "Mali"),("Mareme", 20,
"USA"),("Tapha", 60, "Senegal"))
• Faisons les types de jointure décrit précédemment sur df et df2.
 Les UDF's (User Defined Functions)

val udfFunctionName = udf(scalaFunction)


val udfFunctionName = spark.udf.register("udfFunctionName", Func)

Exercices:
• Créons une fonction qui prend en entrée un Array de String et renvoie au hazard un
élément du Array (utiliser scala.util.Random.nextInt)
• Définissez un UDF du nom de .
• Créer une Array contenant de bons plats.
• Ajouter une nouvelle colonne, dans qui contient les éléments du Array
générés au hazard (en utilisant le UDF).
 Quelques fonctions sur les dates
current_date () : Column Returns the current date as a date column.
date_format(dateExpr: Column, format: Converts a date/timestamp/string to a value of string in the format
String): Column specified by the date format given by the second argument.
to_date(e: Column, fmt: String): Column Converts the column into a `DateType` with a specified format
add_months(startDate: Column, numMonths:
Returns the date that is `numMonths` after `startDate`.
Int): Column
date_add(start: Column, days: Int): Column
Returns the date that is `days` days after `start`
date_sub(start: Column, days: Int): Column
datediff(end: Column, start: Column): Column Returns the number of days from `start` to `end`.
year(e: Column): Column Extracts the year as an integer from a given date/timestamp/string
month(e: Column): Column Extracts the month as an integer from a given date/timestamp/string
Extracts the day of the week as an integer. Ranges from 1 for a Sunday
dayofweek(e: Column): Column
through to 7 for a Saturday
dayofmonth(e: Column): Column Extracts the day of the month as an integer
dayofyear(e: Column): Column Extracts the day of the year as an integer from a given
Returns the last day of the month which the given date belongs to. For
last_day(e: Column): Column example, input "2015-07-27" returns "2015-07-31" since July 31 is the
last day of the month in July 2015.

Exercices:
• Créons une nouvelle colonne qui calcule le nombre de jour entre
la colonne date et la date d'aujourd'hui.
 Repartitionner un dataframe

 Affichons le nombre de partitions de df.


df.rdd.getNumPartitions

 Diminuons le nombre de partitions avec coalesce()

df.coalesce(n)

 Augmentons le nombre de partitions avec repartition()

df.repartition(n)

 Créer un View

df. createOrReplaceTempView("nomView")

 En utilisant spark.sql, nous pouvons faire des traitements sur le view


en utilisant du sql.

 Exemple:
 Nous pouvons faire un Select … from avec des filtres
spak.sql("select * from nomView where quantite > 50").show(false)
 Nous pouvons agréger les données
 Nous pouvons faire des jointures
 …….

Vous aimerez peut-être aussi