+ All Categories
Home > Data & Analytics > Spark RDD : Transformations & Actions

Spark RDD : Transformations & Actions

Date post: 05-Jan-2017
Category:
Upload: michrafy-mustafa
View: 358 times
Download: 10 times
Share this document with a friend
48
APACHE SPARK RDD : TRANSFORMATIONS, ACTIONS PAS À PAS DR MUSTAPHA MICHRAFY CONTACT : DATASCIENCE.KM@GMAIL.COM
Transcript
Page 1: Spark RDD : Transformations & Actions

APACHE SPARKRDD : TRANSFORMATIONS, ACTIONS PAS À PAS

DR MUSTAPHA MICHRAFY

CONTACT : [email protected]

Page 2: Spark RDD : Transformations & Actions

CONTEXTE

Cette étude a été menée dans le cadre desrencontres de travail organisées auLaboratoire CERMSEM, Centre d'Économie dela Sorbonne (CES).

2

M.MICHRAFY

Page 3: Spark RDD : Transformations & Actions

PLAN

1. Contexte2. Objectif et prérequis3. Spark Définition et motivations4. Positionnement de Spark dans l’eco-systeme Big Data5. Composants de spark6. Spark driver et workers7. Apache Spark : vue logique et APIs8. Vue globale sur les API Spark : dépendance et interaction9. RDD, caractéristiques, création et Operations10.Opérations de type transformation et action

3

M.MICHRAFY

Page 4: Spark RDD : Transformations & Actions

OBJECTIF ET PRÉREQUIS

• Connaissance de l’approche objet• Connaissance de la programmation

fonctionnelle • Connaissance du langage Scala

Cette étude vise à mettre en pratique Sparkpas à pas. Il s’agit d’explorer les opérations(transformations et actions) relatives à lastructure résiliente « RDD ».

PrérequisPrérequisObjectifObjectif

4

M.MICHRAFY

Page 5: Spark RDD : Transformations & Actions

SPARK DÉFINITION ET MOTIVATIONS

• Framework open source dédié au calcul distribué• Extension du design pattern map-reduce• Différents modes de traitement : interactif et

streaming• Exécution en mémoire• Intervient dans le traitement de données dans un

écosystème Big-Data

• Rapide• 10 fois plus rapide que Hadoop sur disque• 100 fois plus rapide en mémoire que Hadoop

• Facile à développer• Riche en terme d’opérations• Ecriture rapide des programmes• Mode interactif• Code concis

• Déploiement flexible : Yarn, Standlone, Local, Mesos• Stockage : HDFS, S3, Openstack Swift, MapR FS,

Cassandra• Modèle de développement unifié : Batch, streaming,

interactif• Multi-langages : Scala, Java, Python, R

Apache spark ?Apache spark ? MotivationsMotivations

5

M.MICHRAFY

Page 6: Spark RDD : Transformations & Actions

POSITIONNEMENT DE SPARK DANS L’ECO-SYSTEME BIG DATA

6

Batch/ETL processing

Spark, MapReduce, Pig, Hive

Stream processing

Spark Streaming, Storm, Flink Streaming

Machine Learning

Spark MLib, Mahout, Flink ML, R

Interrogation SQL-Like

Spark SQL, Drill, Hive, Impala

Graph processing

Spark GraphX, Giraph, GraphLab

HDFS, S3, Openstack swift, MapR FS, Cassandra

Stockage

M.MICHRAFY

Page 7: Spark RDD : Transformations & Actions

COMPOSANTS DE SPARK

7

Cluster ManagerSparkContext

Spark driver

Worker Node

Executor

TaskTask

Worker Node

Executor

TaskTask

Worker Node

Executor

TaskTask

M.MICHRAFY

Page 8: Spark RDD : Transformations & Actions

SPARK DRIVER ET WORKERS

8

SparkContext

Spark driver

Cluster Manager

LocalThreads

WorkerExecutor

WorkerExecutor

HDFS, S3, Openstack swift, MapR FS, CassandraHDFS, S3, Openstack swift, MapR FS, Cassandra

• Un programme Spark est composé de deux programmes :

1. Le programme pilote ( driver program )2. Les programmes travailleurs (workers program)

• Les programmes travailleurs s’exécutent soit sur les nœuds du cluster soit sur les threads en local

• Le programme pilote interagit avec le cluster via SparkContext

• Pas de communication entre les programmes travailleurs

M.MICHRAFY

Page 9: Spark RDD : Transformations & Actions

9

Spark Core

RDD (Transformations et Action)

Spark SQL Spark MLSparkStreaming

Spark GraphX SparkR

Système de stockage

� Spark supporte plusieurs systèmes de stockage: HDFS, S3, Openstack swift, MapR FS,Cassandra

� Spark SQL est un module dédié au traitementdes données structurées avec une syntaxesimilaire à SQL. Il permet d’extraire, transformeret charger des données sous différents formats(CSV, JSON, Parquet, base de données) et lesexposer pour des requêtes ad-hoc.

� Spark ML est une librairiedédiée aux méthodesd’apprentissage distribués :

� Classification� Clustering� Régression� Filtrage collaboratif� Réduction de dimension

� Spark Core est le moteur de calcul etd’exécution pour la plateforme Spark :� Ordonnancement des taches� Gestion du calcul en mémoire� Recouvrement� Interaction avec le système de stockage

� API RDD propose des opérations de typetransformation et Action.

� Spark Streaming est dédié au traitementtemps-réel des données en flux. Il offre unmode de traitement en micro-batch etsupportant différentes sources de données(Kafka, Flume, Kinesis ou TCP sockets …).

� Spark GraphX est dédié au traitement et à laparallélisation de graphes. Ce module offre desopérateurs et des algorithmes pour letraitement des graphes. GraphX étend les RDDde Spark via la Resilient Distributed DatasetGraph (RDDG)

� SparkR est un package R offrant une interfacelégère pour utiliser Spark à partir de R. DansSpark 2.0.2, SparkR fournit une implémentationde la Dataframe distribuée supportant desopérations telles que la sélection, le filtrage,l'agrégation. SparkR offre aussi des algorithmesd’apprentissages distribués.

APACHE SPARK : VUE LOGIQUE ET APIS M.MICHRAFY

Page 10: Spark RDD : Transformations & Actions

VUE GLOBALE SUR LES API SPARK : DÉPENDANCE ET INTERACTION

10

Spark core

RDDRDDRDD

Spark SQL

DataframeDataframeDataframe

Spark ML

Model MLModel MLModel ML

Spark GraphX

Graph RDDGraph RDDGraph RDD

Spark Streaming

DStreamDStreamDStream

Streaming Source

File System Data Source

M.MICHRAFY

Page 11: Spark RDD : Transformations & Actions

RDD, CARACTÉRISTIQUES, CRÉATION ET OPERATIONS (1)

11

1. Une RDD est une liste de partitions2. Une RDD est associée à une liste de

dépendances avec les RDD parents3. Une RDD dispose d’une fonction pour calculer

une partition4. Optionnellement, un objet « partionner » pour

les RDD de type clé/valeur5. Optionnellement, une liste indiquant

l’emplacement pour chaque partition

CaractéristiquesCaractéristiques

� RDD supporte deux type d’opérations1. Transformation2. Action

� Une transformation consiste àappliquer une fonction sur 1 à n RDDet à retourner une nouvelle RDD

� Une action consiste à appliquer unefonction et à retourner une valeur

OpérationsOpérations

1. Les transformations sontparesseuses, évitant le calcul inutile.Ceci favorise l’optimisation dutraitement.

2. Une RDD transformée est calculéelorsqu’une action est appliquée surcette dernière.

Evaluation LazyEvaluation Lazy

Resilient Distributed Dataset (RDD)

Resilient : supporte la tolérance aux pannes grâce à unemodélisation du processus d’exécution par un DAG (directedacyclic graph), et au recalcul des partitions manquantes.

Distributed : données distribuées sur les nœuds du cluster.

Dataset : collection de données partitionnée.

M.MICHRAFY

Page 12: Spark RDD : Transformations & Actions

RDD, CARACTÉRISTIQUES, CRÉATION ET OPERATIONS (2)

12

� Trois manières de créer une RDD1. A partir d’une source de données2. En parallélisant une collection via

SparkContext3. En appliquant une opération de

type transformation sur la RDD

CréationCréation

� Certaines fonctions sont disponiblesseulement sur certains types de RDD :

1. mean, variance, stdev pour les RDDnumériques

2. Join pour les RDD clé/valeur3. L’enregistrement de fichier utilisant

des RDD basées sur des fichiers deformat séquentiel.

� Pour plus de détails, voir les RDD de typeo PairRDDFunctions,o DoubleRDDFunctions,o SequenceFileRDDFunctions

Fonction/type RDDFonction/type RDD

In-MemoryImmutable

Lazy

evaluated

Lazy

evaluated

CacheableParallele

TypedPartitioned

Resilient

RDD

� Spark supporte de charger oud’enregistrer des fichiers dansdivers formats : non structuré, semi-structuré, structuré.

� Les formats sont :o Texto Jsono CSVo SequenceFileo Protocole bufferso Object files

Formats fichiersFormats fichiers

M.MICHRAFY

Page 13: Spark RDD : Transformations & Actions

13

Opérations de type transformation et action

• Cette section présente les différentes opérations( Transformation, Action) relatives à un type RDD.

• Elle est organisée par fiche.• Chaque fiche porte sur une opération et contient :

1. Un objectif2. La signature de l’opération3. Une section « À retenir »4. Un exemple exécuté en mode interactif (*)

(*) : Les exemple du code ont été exécutés avec spark-shell, version 2.0.2

M.MICHRAFY

Page 14: Spark RDD : Transformations & Actions

OPÉRATION DE TRANSFORMATION : MÉTHODE MAP

� La méthode map retourne une RDDen appliquant une fonction passéeen argument à chaque item de laRDD source

� Il s’agit d’un design patternincontournable de la programmationfonctionnelle.

ObjectifObjectif

def map[U](f: (T) ⇒ U)(implicit arg0: ClassTag[U]): RDD[U]

API : scala, Classe : RDD, Package : org.apache.spark

Entrée : f est une fonction : (T) => USortie : une RDD de type U

SignatureSignature

// créer un RDD

val x = sc.parallelize(List( 7, 10, 12, 17, 19), 2) // x: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[2] at parallelize at <console>:24

// definir une fonction f

val f = (a:Int) => (a/2, a%2) // f: Int => (Int, Int) = <function1>

// définir une fonction g

val g = (a:Int) => (a*100.0)/20 // g: Int => Double = <function1>

// applique map avec f et g

val zf = x.map(f) // zf: org.apache.spark.rdd.RDD[(Int, Int)] = MapPartitionsRDD[3] at map at <console>:28

val zg = x.map(g) // zg: org.apache.spark.rdd.RDD[Double] = MapPartitionsRDD[4] at map at <console>:28

// afficher zf et zg

zf.collect() // res1: Array[(Int, Int)] = Array((3,1), (5,0), (6,0), (8,1), (9,1))

zg.collect() // res2: Array[Double] = Array(35.0, 50.0, 60.0, 85.0, 95.0)

ExempleExemple

� La RDD source et la RDD retournée ont le même nombre d’item

� Si les items de la RDD source sont de type T alors les items de la RDD retournée sont de type f(T)

À retenirÀ retenir

14

M.MICHRAFY

Page 15: Spark RDD : Transformations & Actions

OPÉRATION TERMINALE : MÉTHODE REDUCE

� La méthode reduce agrège leséléments de la RDD source enappliquant une fonctioncommutative et associative passéeen argument.

� C’est une opération terminale� Il s’agit d’un design pattern

incontournable de la programmationfonctionnelle.

ObjectifObjectif

def reduce(f: (T, T) ⇒ T): T

API : scala, Classe : RDD, Package : org.apache.spark

Entrée : f est une fonction : (T,T) => TSortie : une valeur de retour de type T

SignatureSignature

// créer une RDD comportant les éléments de 1 à 10

val x = sc.parallelize(1 to 10, 3) //x: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[5] at parallelize at <console>:24

// définir une fonction add

val add = (_:Int, _:Int) => x$1 + x$2 // add: (Int, Int) => Int = <function2>

// calculer la somme de 1 à 10 en appliquant reduce

val s = x.reduce(add) // s: Int = 55

ExempleExemple

� Soit une loi * interne sur l’ensemble E.

� La loi * est associative SSI pour tout x,y,z de E on a : x *(y*z) = (x*y)*z

� La loi * est commutative SSI pour tout x, y de E on a : x * y = y * x

À retenirÀ retenir

15

M.MICHRAFY

Page 16: Spark RDD : Transformations & Actions

OPÉRATION DE TERMINALE : MÉTHODE COUNT

� La méthode count retourne lenombre d’éléments d’une RDDsource.

� C’est une opération terminale

ObjectifObjectif

def count(): Long

API : scala, Classe : RDD, Package : org.apache.spark

Sortie : le nombre d’élements de la RRD, de type Long

SignatureSignature

// créer une RDD comportant les éléments de 1 à 10

val x = sc.parallelize(1 to 10, 3) //x: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[6] at parallelize at <console>:24

val y = sc.parallelize(List((1,1), (1,2), (3,5), (3,7), (8,9), (8,13))) // y: org.apache.spark.rdd.RDD[(Int, Int)] = ParallelCollectionRDD[7] at parallelize at <console>:24

// afficher le nombre d’éléments de chaque rdd

x.count() // res3: Long = 10

y.count() // res4: Long = 6

// appel de count sans parenthèses

x.Count // res5: Long = 10

ExempleExemple

� Les parenthèses ne sont pas obligatoires lors de l’appel de count.

� Ceci relève d’une règle en scala : pour toute méthode sans argument, les parenthèse sont optionnelles.

À retenirÀ retenir

16

M.MICHRAFY

Page 17: Spark RDD : Transformations & Actions

OPÉRATION DE TERMINALE : MÉTHODE COUNTBYKEY

� La méthode countByKey compte lenombre de valeur par clé et retouneune map

� Cette méthode nécessite une RDDde type (K,V)

� C’est une opération terminale

ObjectifObjectif

def countByKey(): Map[K, Long]

API : scala, Classe : PairRDDFunctions, Package : org.apache.spark

Sortie : Map[K, Long] , la valeur représente le nombre d’éléments par clé K.

SignatureSignature

// créer une x ( chaque entier et ses diviseurs)

val x = sc.parallelize(List((10,2),(10,5), (14,2), (14,7), (30,2), (30,3), (30,5)))

//Sortie : x: org.apache.spark.rdd.RDD[(Int, Int)] = ParallelCollectionRDD[21] at parallelize at <console>:24

val r = x.countByKey()

// Sortie : r: scala.collection.Map[Int,Long] = Map(30 -> 3, 14 -> 2, 10 -> 2)

ExempleExemple

� countByKey est similaire à count� countBuKey est une méthode de la

class PairRDDFunctions.� Attention, cette méthode n’est à

utiliser que si la map retounée est de volume faible.

À retenirÀ retenir

17

M.MICHRAFY

Page 18: Spark RDD : Transformations & Actions

OPÉRATION DE TERMINALE : MÉTHODE FIRST

� La méthode first retourne le premierélément de la RDD source

� C’est une opération terminale

ObjectifObjectif

def first(): T

API : scala, Classe : RDD, Package : org.apache.spark

Sortie : le premier élément de la RDD de type T

SignatureSignature

// créer une RDD comportant les éléments de 1 à 10

val x = sc.parallelize(1 to 10, 3) //x: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[8] at parallelize at <console>:24

val y = sc.parallelize(List((1,1), (1,2), (3,5), (3,7), (8,9))) // y: org.apache.spark.rdd.RDD[(Int, Int)] = ParallelCollectionRDD[9] at parallelize at <console>:24

val z = sc.parallelize(List())

// afficher le nombre d’éléments de chaque rdd

x.first() // res6: Int = 1

y.first() // res7: (Int, Int) = (1,1)

// Lors de cet appel, une exception se déclenche

z.first() // java.lang.ArrayStoreException: [Ljava.lang.Object;

ExempleExemple

� Les parenthèses ne sont pas obligatoires lors de l’appel de first.

� Une exception se déclenche si l’appel de first() se fait sur une RDD source sans élément.

À retenirÀ retenir

18

M.MICHRAFY

Page 19: Spark RDD : Transformations & Actions

OPÉRATION DE TERMINALE : MÉTHODE TAKE

� La méthode take retourne untableau d’éléments, constitué des npremiers éléments de la RDD source.

� Le nombre d’éléments à retourner estl’argument de la méthode take

� C’est une opération terminale

ObjectifObjectif

def take(num: Int): Array[T]

API : scala, Classe : RDD, Package : org.apache.spark

Entrée : num le nombre de éléments à retournerSortie : un tableau de type T

SignatureSignature

// créer une RDD comportant les éléments de 1 à 10

val x = sc.parallelize(1 to 10, 3) // x: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[10] at parallelize at <console>:24

val z = sc.parallelize(List()) // z: org.apache.spark.rdd.RDD[Nothing] = ParallelCollectionRDD[11] at parallelize at <console>:24

// appliquer la méthode take sur la rdd x

x.take(-3) // res8: Array[Int] = Array()

x.take(0) // res9: Array[Int] = Array()

x.take(2) // res10: Array[Int] = Array(1, 2)

z.take(-5) // res11: Array[Nothing] = Array()

z.take(3) // déclenche une exception

ExempleExemple

� Si le num est négatif, la valeur de retour est un tableau vide (Array())

� Si num est supérieur au nombre d’éléments de la RDD, alors tous les éléments de RDD sont retournés.

� Si la RDD est vide (sans élément), alors l’appel à take avec une valeur strictement positif lève une exception

À retenirÀ retenir

19

M.MICHRAFY

Page 20: Spark RDD : Transformations & Actions

OPÉRATION DE TERMINALE : MÉTHODE FLATMAP

� La méthode flatMap transformechaque Item de la RDD source en0 ou plusieurs items et retourneune nouvelle RDD.

� Il s’agit d’un design patternincontournable de laprogrammation fonctionnelle.

ObjectifObjectif

def flatMap[U](f: (T) ⇒ TraversableOnce[U])(implicitarg0: ClassTag[U]): RDD[U]

API : scala, Classe : RDD, Package : org.apache.spark

Entrée : f est une fonction : (T) ⇒ TraversableOnce[U]Sortie : Une RDD[U]

SignatureSignature

// créer une RDD comportant les éléments de 1 à 10

val x = sc.parallelize(List((1,2),(3,5),(8,10))

// définir une fonction f

val f = (a:Tuple2[Int,Int]) => Seq(a._1, a._2)

// appliquer flatMap sur x

Val y = x.flatMap(f)

// afficher les éléments de y

y.collect()

//Sortie : res1: Array[Int] = Array(1, 2, 3, 5, 8, 10)

ExempleExemple

� flatMap est similaire à Map� La fonction f doit retourner un trait

de type TraversableOnce qui consiste à parcourir une collection une ou plusieurs fois.

À retenirÀ retenir

val z = parallelize(List("La meilleure facon de predire l’avenir est de le creer", "Celui qui

veut reussir trouve un moyen", "Celui qui veut rien faire trouve une excuse"))

val g = (s:String) => s.split(" ").toList

// appliquer la fonction g sur les éléments de z

val t = z.flatMap(g)

// afficher les éléments de t

t.collect()

//Sortie : res2: Array[String] = Array(La, meilleure, faþon, de, predire, l'avenir, est, de, le, creer, Celui, qui, veut, reussir, trouve, un, moyen, Celui, qui, veut, rien, faire, trouve, une, excuse)

1 2

20

M.MICHRAFY

Page 21: Spark RDD : Transformations & Actions

OPÉRATION DE TRANSFORMATION : MÉTHODE FILTER

� La méthode filter retourne une RDDne contenant que les items de la RDDsource satisfaisant le prédicat f , passéeen argument.

� Il s’agit aussi d’un design patternincontournable de la programmationfonctionnelle.

ObjectifObjectif

def filter(f: (T) ⇒ Boolean): RDD[T]

API : scala, Classe : RDD, Package : org.apache.spark

Entrée : f est une fonction : (T) => BooleanSortie : une RDD de type T

SignatureSignature

// créer un RDD

val x = sc.parallelize(List( 7, 10, 12, 17, 19), 2) // x: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[0] at parallelize at <console>:24

// definir une fonction f

val f = (a:Int) => (a%2==0) // f: Int => Boolean = <function1>

// définir une fonction g

Val g = (a:Int) => (a>50) // g: Int => Boolean = <function1>

// applique filter avec f et g

val zf = x.map(f) // zf: org.apache.spark.rdd.RDD[Boolean] = MapPartitionsRDD[1] at map at <console>:28

val zg = x.map(g) // zg: org.apache.spark.rdd.RDD[Boolean] = MapPartitionsRDD[2] at map at <console>:28

// afficher zf et zg

zf.collect() // res0: Array[Boolean] = Array(false, true, true, false, false)

Zg.collect() // res2: Array[Boolean] = Array(false, false, false, false, false)

ExempleExemple

� La RDD source et la RDD obtenue ont le même type d’item (T)

� Le nombre d’éléments de la RDD obtenue est toujours inférieur au nombre d’éléments de la RDD source

� Il est possible d’obtenir une RDD sans item.

À retenirÀ retenir

21

M.MICHRAFY

Page 22: Spark RDD : Transformations & Actions

OPÉRATION DE TRANSFORMATION : MÉTHODE SAMPLE

� La méthode sample retourne unéchantillon des données – qui est unesélection aléatoire- de la RDDsource.

ObjectifObjectif

def sample(withRpl: Boolean, fraction: Double, seed: Long = Utils.random.nextLong): RDD[T]

API : scala, Classe : RDD, Package : org.apache.spark

Entrée : withRpl : avec ou sans répétitionfraction : le % des données, dans [0 1]seed : pour initialiser le générateur aléatoire

Sortie : une RDD de type T

SignatureSignature

// créer un RDD de 100 entiers

val x = sc.parallelize(1 to 100, 2) // x: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[3] at parallelize at <console>:24

// Faire une selection aléatoire d’un % de 0,1

val smpl1 = x.sample(true, 0.1, 7) // smpl1: org.apache.spark.rdd.RDD[Int] = PartitionwiseSampledRDD[4] at sample at <console>:26

smpl1.collect() // res3: Array[Int] = Array(3, 6, 14, 47, 48, 72, 78, 84, 87, 92, 100)

// Faire une selection aléatoire d’un % de 0,3

val smpl2 = x.sample(false, 0.3, 17) // smpl2: org.apache.spark.rdd.RDD[Int] = PartitionwiseSampledRDD[6] at sample at <console>:26

smpl2.collect() // res5: Array[Int] = Array(3, 4, 8, 11, 12, 14, 16, 18, 19, 21, 23, 25, 30, 33, 36, 37, 38, 42, 43, 46, 47, 49, 55,

// 58, 61, 64, 69, 70, 73, 74, 76, 80, 86, 89, 96)

ExempleExemple

� Si withRpl = true, on utilise un générateur basé sur la loi de Poisson

� Si withRpl = false, on utilise un générateur basé sur la loi de Bernoulli.

À retenirÀ retenir

22

M.MICHRAFY

Page 23: Spark RDD : Transformations & Actions

OPÉRATION DE TRANSFORMATION: MÉTHODE TAKESAMPLE

� La méthode takeSample retourne untableau – qui est une sélectionaléatoire- de la RDD source.

� Le nombre d’éléments du tableau estun argument de la méthodetakeSample

ObjectifObjectif

def takeSample(withReplacement: Boolean, num: Int, seed: Long = Utils.random.nextLong): Array[T]

API : scala, Classe : RDD, Package : org.apache.spark

Entrée : withRpl : avec ou sans répititionnum : le nombre d’éléments à retournerseed : pour initialiser le générateur aléatoire

Sortie : un tableau de type T (Array[T])

SignatureSignature

// créer un RDD de 100 entiers

val x = sc.parallelize(1 to 100, 2) // x: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[7] at parallelize at <console>:24

val smpl1take = x.takeSample(true, 10, 7) // smpl1take: Array[Int] = Array(19, 29, 64, 52, 74, 87, 93, 46, 27, 31)

val smpl2take = x.takeSample(false, 10, 7) // smpl2take: Array[Int] = Array(41, 80, 72, 24, 90, 100, 56, 87, 50, 78)

ExempleExemple

� Cette méthode retourne exactement un tableau composé de num éléments de la RDD source.

� Elle est différente de la méthode sample puisque sample prend un argument fraction indiquant le % d’éléments à retourner et retourne une RDD.

À retenirÀ retenir

23

M.MICHRAFY

Page 24: Spark RDD : Transformations & Actions

OPÉRATION TERMINALE: MÉTHODE TAKEORDERED

� La méthode takeOrdered ordonneles éléments de données du RDD enutilisant l’ordre implicite (croissant) etrenvoie les n premiers éléments sousforme d’un tableau.

ObjectifObjectif

def takeOrdered(num: Int)(implicit ord: Ordering[T]): Array[T]

API : scala, Classe : RDD, Package : org.apache.spark

Entrée :

num: le nombre d’éléments à retourner

Sortie : un tableau de type T (array[T])

SignatureSignature

sc.parallelize(Seq(6, 8, 9, 1, 2, 3)).takeOrdered(3) // res1: Array[Int] = Array(1, 2, 3)

sc.parallelize(Seq(0, 6, 8, 9, 1, 2, 3)).takeOrdered(3) // res2: Array[Int] = Array(0, 1, 2)

sc.parallelize(Seq((1,2),(1,4),(6,7), (9,11), (8,1))).takeOrdered(3) // res3: Array[(Int, Int)] = Array((1,2), (1,4), (6,7))

sc.parallelize(Seq(("aa",2),("bc",4),("ef",7), ("aa",11), ("ef",1))).takeOrdered(3) // res4: Array[(String, Int)] = Array((aa,2), (aa,11), (bc,4))

ExempleExemple

� Cette méthode est à ne pas utiliser lorsque le tableau retourné est volumineux car les données sont chargées sur la mémoire du driver.

� Les éléments de la RDD source doivent disposer d’une relation d’ordre

À retenirÀ retenir

24

M.MICHRAFY

Page 25: Spark RDD : Transformations & Actions

OPÉRATION TERMINALE : MÉTHODE FOLD

� Agréger les données en deux étapes. Il s’agit d’une opération de type Action.

� L’étape 1 consiste à appliquer op par partition

� L’étape 2 consiste appliquer op sur les résultats de la 1 étape

� op doit être un opérateur associatif

ObjectifsObjectifsdef fold(zeroValue: T)(op: (T, T) ⇒ T): T

API : scala, Classe : rdd, Package : org.apache.spark

Entrée :

- zeroValue : de type T, c est la valeur initiale de calcul

- op est une fonction associative de signature : (T,T) => T

Sortie : une valeur de type T

SignatureSignature

val x = sc.parallelize( 1 to 6, 2) // x: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[0] at parallelize at <console>:24

// calculer la somme de éléments de x via les partitions

val op = (a:Int,b:Int) => a+b // op: (Int, Int) => Int = <function2>

// zeroValue : 0

x.fold(0)((op) // res10: Int = 21

ExempleExemple

� Fold et agrgregate sont similaires en terme de processus

� fold applique le même fonction en 1 et 2 étape

� Aggregate associe une fonction à chaque étape

À retenirÀ retenir

25

M.MICHRAFY

Page 26: Spark RDD : Transformations & Actions

OPÉRATION DE TRANSFORMATION : MÉTHODE MAPPARTITIONSWITHINDEX

� Calculer une nouvelle RDD en appliquant une fonction f sur chaque partition

� il nécessite au moins un paramètre de type fonction qui prend en entrée les éléments d’une partition et son index

ObjectifsObjectifsdef mapPartitionsWithIndex[U](f: (Int, Iterator[T]) ⇒ Iterator[U],

ind: Boolean = false)(implicit arg0: ClassTag[U]): RDD[U]

API : scala, Classe : rdd, Package : org.apache.spark

Entrée :

- f est une fonction (Int, Iterator[T]) ⇒ Iterator[U]

- ind est boolean, dont la valeur par défaut est false,

Sortie : RDD[U]

SignatureSignature

// définir un RDD ( 1 …10) avec 3 partitions

val x = sc.parallelize(1 to 10, 3) // x: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[12] at parallelize at <console>:24

// affiche une liste de tuple, chaque tuple est composé de l'index de la partition et la valeur de l'élément.def f[T](i:Int, p:Iterator[T]) : Iterator[(Int,T)] = p.map(w => (i,w)) // f: [T](i: Int, p: Iterator[T])Iterator[(Int, T)]

val y = x.mapPartitionsWithIndex(f) // y: org.apache.spark.rdd.RDD[(Int, Int)] = MapPartitionsRDD[13] at mapPartitionsWithIndex at <console>:28

y.collect() // res8: Array[(Int, Int)] = Array((0,1), (0,2), (0,3), (1,4), (1,5), (1,6), (2,7), (2,8), (2,9), (2,10))

ExempleExemple

� Il est similaire à map� map applique une fonction sur

les éléments de la RDD alors que mapPartitionsWithIndexapplique une fonction f à chaque partition

À retenirÀ retenir

26

M.MICHRAFY

Page 27: Spark RDD : Transformations & Actions

OPÉRATION TERMINALE : MÉTHODE AGGREGATE

� Agréger les données en deux étapes. Il s’agit d’une opération de type Action

� L’étape 1 consiste à appliquer seqOp par partition

� L’étape 2 consiste à appliquer combOpaux résultats de l’étape 1

ObjectifsObjectifsdef aggregate[U](zeroValue: U)(seqOp: (U, T) ⇒ U,

combOp: (U, U) ⇒ U)(implicit arg0: ClassTag[U]): U

API : scala, Classe : rdd, Package : org.apache.spark

Entrée- zeroValue : la valeur initiale de l’accumulateur de type U

- seqOp : c’est une fonction associative qui sera appliquée sur chaque partition

- comOp : c’est une fonction associative qui s’applique sur les résulats données par seqOp.

Sortie : une valeur de retour de type U

SignatureSignature

val x = sc.parallelize( 1 to 6, 2) // x: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[0] at parallelize at <console>:24

// calculer la somme de éléments de x via les partitions

val seqOp = (a:Int,b:Int) => if(a>b) a else b // seqOp: (Int, Int) => Int = <function2>

val compOp = (a:Int,b:Int) => a + b // compOp: (Int, Int) => Int = <function2>

// affiche une liste de tuple, chaque tuple est composé de l'index de la partition et la valeur de l'élément.def f[T](i:Int, p:Iterator[T]) : Iterator[(Int,T)] = p.map(w => (i,w)) // f: [T](i: Int, p: Iterator[T])Iterator[(Int, T)]

// afficher chaque élément et sa partitionx.mapPartitionsWithIndex(f).collect() // res4: Array[(Int, Int)] = Array((0,1), (0,2), (0,3), (1,4), (1,5), (1,6), (2,7), (2,8), (2,9), (2,10))

// appliquer la méthode aggregate sur la RDD X

x.aggregate(0)( seqOp, compOp) // res10: Int = 19

ExempleExemple

27

M.MICHRAFY

Page 28: Spark RDD : Transformations & Actions

OPÉRATION DE TRANSFORMATION : MÉTHODE MAPVALUES

� La méthode mapValues, s’applique àune RDD de type (K,V) et retourne uneRDD de type (K,U).

� Cette méthode prend en argumentune fonction f: (V) ⇒ U, et transformechaque pair (K,V) en (K, f(U)).

� C’est une opération de transformation

ObjectifObjectif

def mapValues[U](f: (V) ⇒ U): RDD[(K, U)]

API : scala, Classe : PairRDDFunctions, Package : org.apache.spark

Sortie : RDD[(K, U)]

SignatureSignature

// créer une RDD constitué d’une liste de fruits

val x = sc.parallelize(List("Abricot", "Cerise", "Nectarine", "Noisette", "Kiwi"))

x: org.apache.spark.rdd.RDD[String] = ParallelCollectionRDD[31] at parallelize

at <console>:24

// créer une RDD de type (K,V), avec V = la taille de K

val y = x.map(w => (w,w.length))

y// : org.apache.spark.rdd.RDD[(String, Int)] = MapPartitionsRDD[30] at map

at <console>:26

// /afficher la RDD y

y.collect() // res1: Array[(String, Int)] = Array((Abricot,7), (Cerise,6),

(Nectarine,9), (Raisin,6), (Kiwi,4))

// créer une fonction f

val f = (n:Int) => (n/2, n%2) // f: Int => (Int, Int) = <function1>

ExempleExemple

� La RDD source et la RDD obtenueont :

• La même taille.• Les mêmes clés• Les mêmes partitions

À retenirÀ retenir

28

// appliquer mapValues sur y avec la fonction f

val z = y.mapValues(f)

//Sortie : z: org.apache.spark.rdd.RDD[(String, (Int, Int))] =

MapPartitionsRDD[33] at mapValues at // <console>:30

// afficher le résultat

z.collect()

res2: Array[(String, (Int, Int))] = Array((Abricot,(3,1)), (Cerise,(3,0)),

(Nectarine,(4,1)), (Noisette,(4,0)), (Kiwi,(2,0)))

y.Count == z.count

res49: Boolean = true

1 2

M.MICHRAFY

Page 29: Spark RDD : Transformations & Actions

OPÉRATION TERMINALE : MÉTHODE COLLECT

� La méthode collect retourne un tableau ( Array) qui représente les éléments de la RDD.

� Il est utile lors de la mise au point d’un code.

ObjectifsObjectifsdef collect(): Array[T]

API : scala, Classe : rdd, Package : org.apache.spark

Sortie : Array[T]

SignatureSignature

// définir un RDD ( 1 …10) avec 2 partitions

val x = sc.parallelize(1 to 10, 2) // x: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[14] at parallelize at <console>:24

// appliquer la méthode collect pour obtenir un tableau

val x_arr = x.collect() // x_arr: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

// Appel sans parenthèsex.Collect // res0: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

ExempleExemple

� Cette méthode est couteuse en terme de CPU. Par conséquent, elle est à utiliser seulement si la RDD a un faible volume.

À retenirÀ retenir

29

M.MICHRAFY

Page 30: Spark RDD : Transformations & Actions

OPÉRATION TERMINALE : MÉTHODE FOREACH

� La méthode foreach applique une fonction f (T) => Unit, sur chaque élément de la RDD

� Il est utile lors de la mise au point d’un code.

ObjectifsObjectifsdef foreach(f: (T) ⇒ Unit): Unit

API : scala, Classe : rdd, Package : org.apache.spark

Entrée :f une fonction ( (T) => Unit)

Sortie : pas de valeur de retour (Unit)

SignatureSignature

// définir des RDD

val x = sc.parallelize(1 to 5, 2) // x: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[15] at parallelize at <console>:24val y = sc.parallelize(List("Banane", "Kiwi", "Cerise", "Orange", "Fraise"),2)

val z = y.zip(x) // z: org.apache.spark.rdd.RDD[(String, Int)] = ZippedPartitionsRDD2[17] at zip at <console>:28

// afficher les éléments de la RDD xx.foreach(w => print(w + ", ")) // 1, 3, 4, 5, 2,

// afficher les éléments de la RDD yy.foreach(w => print(w + ", ")) // Cerise, Orange, Banane, Fraise, Kiwi,

// afficher les éléments de la RDD zz.foreach(w => print(w + ", ")) // (Banane,1), (Cerise,3), (Orange,4), (Kiwi,2), (Fraise,5),

Exemple

� Attention, foreach n’affiche pas forcement la même chose que la méthode collect

À retenirÀ retenir

30

M.MICHRAFY

Page 31: Spark RDD : Transformations & Actions

OPÉRATION DE TRANSFORMATION : MÉTHODE COLLECT AVEC DES ARGUMENTS

� Elle retourne une RDD comportant les éléments correspondant à l'application d’une fonction partielle

� Cette méthode est couteuse en terme de CPU. Par conséquent, elle est à utiliser seulement si la RDD a un faible volume.

ObjectifsObjectifs

collect[U](f: PartialFunction[T, U])(implicit arg0: ClassTag[U]): RDD[U]

API : scala, Classe : rdd, Package : org.apache.spark

Sortie : Array[T]

SignatureSignature

// créer une rdd avec des éléments de 1 à 10

val sample = sc.parallelize(1 to 10) // sample: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[18] at parallelize at <console>:24

// Déclarer une fonction partielle

val isEven: PartialFunction[Int,Int] = { case x if x % 2 == 0 => x } // isEven: PartialFunction[Int,Int] = <function1>

// appel de la méthode collect avec l’argument isEven (la fonction partielle)

val sample_fp = sample.collect(isEven) // sample_fp: org.apache.spark.rdd.RDD[Int] = MapPartitionsRDD[22] at collect at <console>:30

// afficher les élements de la rdd sample_fp

sample_fp.collect() // res11: Array[Int] = Array(2, 4, 6, 8, 10)

ExempleExemple

� Elle est similaire à la méthode collect sans argument.

� collect() retourne un tableau alors que collect(PartialFunction) retourne une RDD [U] après avoir appliqué la fonction partielle sur les items de la RDD.

À retenirÀ retenir

31

M.MICHRAFY

Page 32: Spark RDD : Transformations & Actions

OPÉRATION DE TRANSFORMATION : MÉTHODE DISTINCT

� La méthode distinct retourne une RDD qui comporte les éléments distincts de la RDD source

ObjectifsObjectifsdef distinct(): RDD[T]

API : scala, Classe : rdd, Package : org.apache.spark

Sortie : RDD[T]

SignatureSignature

// créer un rdd avec les éléments : 1,1,2,3,4,5,5

val z = sc.parallelize(List(1,1,2,3,4,5,5)) // z: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[23] at parallelize at <console>:24

// appliquer la méthode distinct sur la rdd z

val zsd = z.distinct() // zsd: org.apache.spark.rdd.RDD[Int] = MapPartitionsRDD[26] at distinct at <console>:26

// regrouper le resultat dans un tableau

zsd.collect() // res12: Array[Int] = Array(4, 1, 5, 2, 3)

val l = List(List(1,2),List(3,4), List(4,3), List(1,2), List(1,2,3,4)) // l: List[List[Int]] = List(List(1, 2), List(3, 4), List(4, 3), List(1, 2), List(1, 2, 3, 4))

val zobj = sc.parallelize(l) // zobj: org.apache.spark.rdd.RDD[List[Int]] = ParallelCollectionRDD[27] at parallelize at <console>:26

// observer le resultat

val zobjsd = zobj.distinct() // zobjsd: org.apache.spark.rdd.RDD[List[Int]] = MapPartitionsRDD[30] at distinct at <console>:28

zobjsd.collect() // res14: Array[List[Int]] = Array(List(3, 4), List(1, 2, 3, 4), List(4, 3), List(1, 2))

ExempleExemple

� Il est possible de mettre en place la méthode distinct en utilisant :

• map• reduceByKey

À retenirÀ retenir

32

M.MICHRAFY

Page 33: Spark RDD : Transformations & Actions

OPÉRATION DE TRANSFORMATION : MÉTHODE UNION

� La méthode union retourne une RDD qui est l’union des items de la RDD source et de la RDD passée en argument.

� il est possible d’avoir des éléments identiques dans la RDD résultat. Pour éviter cela, utiliser la méthode distinct

ObjectifsObjectifs

def union(other: RDD[T]): RDD[T]

API : scala, Classe : rdd, Package : org.apache.spark

Entrée : other est de type RDD[T].

Sortie : RDD[T]

SignatureSignature

// créer les rdd avec les éléments : 1 to 10, et 5 to 15

val x = sc.parallelize(1 to 10) // x: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[31] at parallelize at <console>:24

val y = sc.parallelize(5 to 15) // y: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[32] at parallelize at <console>:24

// appliquer la méthode union

val uad = x.union(y) // uad: org.apache.spark.rdd.RDD[Int] = UnionRDD[33] at union at <console>:28

// appliquer la méthode union et supprimer les éléments identiques

val usd = x.union(y).distinct() // usd: org.apache.spark.rdd.RDD[Int] = MapPartitionsRDD[37] at distinct at <console>:28

// afficher les résultats

uad.collect() // res15: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)

usd.collect() // res16: Array[Int] = Array(8, 1, 9, 10, 2, 11, 3, 4, 12, 13, 5, 14, 6, 15, 7)

ExempleExemple

� Les éléments de la RDD source et la rdd other doivent être de même type (ici T)

� Plus précisément, les éléments de la RDD other doivent être de même type que ceux de la rddsource.

À retenirÀ retenir

33

M.MICHRAFY

Page 34: Spark RDD : Transformations & Actions

OPÉRATION DE TRANSFORMATION : MÉTHODE INTERSECTION

� La méthode intersection retourne une RDD qui est l’intersection des items du RDD source et de la RDD passée en argument.

� Attention, le résultat de retour ne comporte pas de doublant même si la RDD source ou argument en comporte.

ObjectifsObjectifsdef intersection(other: RDD[T]): RDD[T]

API : scala, Classe : rdd, Package : org.apache.spark

Entrée : other est de type RDD[T].

Sortie : RDD[T]

SignatureSignature

// créer deux rdds

val x = sc.parallelize(List(1 , 1, 2, 3, 4, 7)) // x: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[38] at parallelize at <console>:24

val y = = sc.parallelize(List(1, 1, 4, 4, 5, 6)) // y: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[39] at parallelize at <console>:24

// appliquer la méthode intersection

val z = x. intersection(y) // z: org.apache.spark.rdd.RDD[Int] = MapPartitionsRDD[45] at intersection at <console>:28

// afficher les résultats

z.collect() // res17: Array[Int] = Array(4, 1)

ExempleExemple

� Les éléments de la RDD otherdoivent être de même type que ceux de la rdd source.

� intersection peut être codée avec :

• map,• cogroup• filter

À retenirÀ retenir

34

M.MICHRAFY

Page 35: Spark RDD : Transformations & Actions

OPÉRATION DE TRANSFORMATION : MÉTHODE SUBTRACT

� La méthode subtract est l’implémentation de l’opération soustraction au sens ensemble.

� Elle retourne les éléments de la RDD source mais qui ne sont pas dans la RDD passée en argument.

ObjectifsObjectifsdef subtract(other: RDD[T]): RDD[T]

API : scala, Classe : rdd, Package : org.apache.spark

Entrée : other est de type RDD[T]

Sortie : RDD[T]

SignatureSignature

// créer les 2 rdds

val x = sc.parallelize(1 to 5, 2)

val y = sc.parallelize(3 to 7, 2)

x.collect() // res18: Array[Int] = Array(1, 2, 3, 4, 5)

y.collect() // res19: Array[Int] = Array(3, 4, 5, 6, 7)

// appliquer la méthode subtract et generer la RDD s

val s = x.subtract(y)

// afficher les éléments

s.collect() // res20: Array[Int] = Array(2, 1)

ExempleExemple

� La RDD other doit être de même type que la RDD source. Dans le cas contraire, on obtient une erreur.

� Il existe des variante de subtractportant sur le nombre des partitions.

À retenirÀ retenir

// créer une RDD

val z = sc.parallelize(List("A","B","D","E"),2)

// appliquer la méthode subtract sur x et z

// cette instruction génère une erreur

val t = x.subtract(z)

error: type mismatch;

found : org.apache.spark.rdd.RDD[String]

required: org.apache.spark.rdd.RDD[Int]

val t = x.subtract(z)

1 2

35

M.MICHRAFY

Page 36: Spark RDD : Transformations & Actions

OPÉRATION DE TRANSFORMATION : MÉTHODE ZIP

� La méthode zip consiste à construire une RDD de type (K,V) à partir de la RDD[K] source et la RDD[V] passée en argument.

� L’élément i de la RDD résultante est (ki,vi) avec ki, vi les éléments d’indice i resp. des RDD source et argument.

ObjectifsObjectifsdef zip[U](other: RDD[U])(implicit arg0: ClassTag[U]): RDD[(T, U)]

API : scala, Classe : rdd, Package : org.apache.spark

Entrée : other est de type RDD[U].

Sortie : un RDD de type (T,U)

SignatureSignature

// créer les deux rdds

val key = sc.parallelize(1 to 5, 2)

val value = sc.parallelize(11 to 15, 2 )

// appliquer la méthode zip

val x = key.zip(value)

// afficher les éléments

x.collect() // res21: Array[(Int, Int)] = Array((1,11), (2,12), (3,13), (4,14), (5,15))

Exemple 1Exemple 1

� Pour réaliser une opération zip, les deux RDD doivent avoir :

• Le même nombre de partitions

• Le même nombre d'éléments dans chaque Partition

À retenirÀ retenir

// créer deux rdds

val value_nes = sc.parallelize(11 to 16, 2 )

val value_nps = sc.parallelize(11 to 15, 3 )

// appliquer la méthode zip

val x_nes = key.zip(value_nes)

val x_nps = key.zip(value_nep)

// Des exceptions se lèvent lors de l’appel de collect

X_nex.collect() // error : Can only zip RDDs with same number of elements in each partition

x_nep.collect() // error : Can't zip RDDs with unequal numbers of partitions

Exemple 2Exemple 2

36

M.MICHRAFY

Page 37: Spark RDD : Transformations & Actions

OPÉRATION DE TRANSFORMATION : MÉTHODE GROUPBY

� La méthode groupBy regroupe les éléments de la RDD[T] source par clé et retourne une RDD [(k, Iterable[T])]

� Elle prend en entrée une fonction f : (T) => K, qui s’applique à chaque élément de la RDD source pour générer les clés de la RDD retournée.

ObjectifObjectifdef groupBy[K](f: (T) ⇒ K)(implicit kt: ClassTag[K]): RDD[(K, Iterable[T])]

API : scala, Classe : RDD

Package : org.apache.spark

Sortie : RDD[(K, Iterable[T])]

SignatureSignature

// créer la rdd de type (Int) avec 10 partitions

val x = sc.parallelize(1 to 20, 10)

// faire une selection aléatoire dans les éléments de x

val y = x.sample(false, 0.1, 19)

// definir la function f

val f = (w:Int) => w%3 // f: Int => Int = <function1>

// définir une fonction g

val g = (w:Int) => 2*w + 7 // g: Int => Int = <function1>

ExempleExemple

� Cette méthode est très couteuse.� Il existe deux variantes de cette méthode,

prenant en plus soit le nombre de partitions, soit un partitionner

� Attention la RDD est de type (K, Iterable[T])], sachant que f : (T) => K

� Elle est similaire avec la méthode groupByKey

À retenirÀ retenir

// appliquer la groupBy , avec f, sur les éléments de y

val z = y.groupBy(f)

// appliquer groupBy, avec g, sur les éléments de y

val s = y.groupBy(g)

// afficher z et s

z.collect() // res25: Array[(Int, Iterable[Int])] = Array((0,CompactBuffer(6, 15)))

s.collect() // res26: Array[(Int, Iterable[Int])] = Array((37,CompactBuffer(15)), (19,CompactBuffer(6)))

1 2

37

M.MICHRAFY

Page 38: Spark RDD : Transformations & Actions

OPÉRATION DE TRANSFORMATION : MÉTHODE GROUPBYKEY

� Pour une RDD de type (K, V), groupByKey retourne une RDD de type (K,Iterable<V>)

� Si le regroupement vise une agrégation, pour des raisons de performance, il est conseillé d’utiliser reduceByKey ou aggregateByKey.

ObjectifObjectifdef groupByKey(): RDD[(K, Iterable[V])]

API : scala, Classe : PairRDDFunctions,

Package : org.apache.spark

Sortie : RDD[(K, Iterable[V])]

SignatureSignature

// créer la rdd de type (k,v) avec deux partitions

val x = sc.parallelize(List((1,1),(11,2),(11,6),(2,8),(3,5),(3,7)),2) // x: org.apache.spark.rdd.RDD[(Int, Int)] = ParallelCollectionRDD[67] at parallelize at <console>:24

// appliquer la méthode groupeByKey pour regrouper par clé

val z = x.groupByKey() // z: org.apache.spark.rdd.RDD[(Int, Iterable[Int])] = ShuffledRDD[68] at groupByKey at <console>:26

// afficher les données de la RDD z

z.collect() // res27: Array[(Int, Iterable[Int])] = Array((2,CompactBuffer(8)), (11,CompactBuffer(2, 6)), (1,CompactBuffer(1)), (3,CompactBuffer(5, 7)))

ExempleExemple

� groupByKey est une méthode de la classe PairRDDFunctions. Elle s’applique à des RDD de type

(k,v).

� groupByKey utilise un partitionner par défaut� Il existe différente variante de cette méthode : - def groupByKey(numPartitions: Int): RDD[(K, Iterable[V])]- def groupByKey(partitioner: Partitioner): RDD[(K, Iterable[V])]

À retenirÀ retenir

38

M.MICHRAFY

Page 39: Spark RDD : Transformations & Actions

OPÉRATION DE TRANSFORMATION : MÉTHODE REDUCEBYKEY

� Pour une RDD de type (k,v),reduceByKey retourne une RDD detype (k,v) où les valeurs de chaqueclé sont agrégées en utilisant lafonction f de type (v,v) => v.

ObjectifObjectifdef reduceByKey(func: (V, V) ⇒ V): RDD[(K, V)]

API : scala, Classe : PairRDDFunctions, Package :

org.apache.spark

Entrée : une fonction associative, commutative de type (v,v) => v

Sortie RDD[(K, V)]

SignatureSignature

// créer la rdd de type (k,v) avec deux partitions

val t = Seq((1,1),(1,8), (2,7), (2,9), (3,13), (3, 10))

val x = sc.parallelize(t, 2) // // x: org.apache.spark.rdd.RDD[(Int, Int)] = ParallelCollectionRDD[4] at parallelize at <console>:24

// créer la fonction func

val func = (x:Int, y:Int) => x + y // func: (Int, Int) => Int = <function2>

// appliquer la méthode reduceByKey pour regrouper par clé et appliquer func

val y = x.reduceByKey(func) // y: org.apache.spark.rdd.RDD[(Int, Int)] = ShuffledRDD[5] at reduceByKey at <console>:32

x.collect() // // res2: Array[(Int, Int)] = Array((1,1), (1,8), (2,7), (2,9), (3,13), (3,10))

// afficher les résultats

y.collect() // res3: Array[(Int, Int)] = Array((2,16), (1,9), (3,23))

ExempleExemple

� reduceByKey estune méthode de la classe PairRDDFunctions.

� il existe deux variantes de cette méthode nécessitant en plus soit le nombre de partitions soit un partitionner.

À retenirÀ retenir

39

M.MICHRAFY

Page 40: Spark RDD : Transformations & Actions

OPÉRATION DE TRANSFORMATION : MÉTHODE AGGREGATEBYKEY

� Pour une RDD[(k,v)], aggregateByKeyretourne une RDD[(k,u)] où les valeursde chaque clé sont agrégées enappliquant les fonctions seqOp etcombOp et la valeur neutrezeroValue.

� Elle est similaire à aggregate saufque l'agrégation est appliquée auxvaleurs ayant la même clé

ObjectifObjectif

def aggregateByKey[U](zero: U)(seqOp: (U, V) ⇒ U, combOp: (U, U) ⇒ U)(implicit arg0: ClassTag[U]): RDD[(K, U)]

API : scala, Classe : PairRDDFunctions,

Package : org.apache.spark

Entrée : zero valeur neutre de type U

seqOp : (U,V) => U et CombOp : (U,U) => U

Sortie : RDD[(K, V)]

SignatureSignature

// créer la rdd de type (k,v) avec deux partitions

val x = sc.parallelize(List(("Bannane", 4),("Fraise", 1),("Bannane", 3),("Kiwi", 2),("Fraise", 2),("Orange", 5),("Orange",6),("Raisin",4)),2)

// Pour chaque élément de la RDD x, afficher sa partition et sa valeur

x.mapPartitionsWithIndex((i,p) => p.map(w => (i,w))).collect()

// res28: Array[(Int, (String, Int))] = Array((0,(Bannane,4)), (0,(Fraise,1)), (0,(Bannane,3)), (0,(Kiwi,2)), (1,(Fraise,2)), (1,(Orange,5)), (1,(Orange,6)), (1,(Raisin,4)))

// créer deux fonctions seqOp et combOp

val seqOp = (a:Int, b:Int) => Math.max(a,b) // seqOp: (Int, Int) => Int = <function2>

val combOp = (a:Int, b:Int) => a + b // combOp: (Int, Int) => Int = <function2>

// appliquer la méthode aggregateByKey

val y = x.aggregateByKey(0)(seqOp, combOp) // y: org.apache.spark.rdd.RDD[(String, Int)] = ShuffledRDD[76] at aggregateByKey at <console>:30

// afficher les résultats

y.collect() // res29: Array[(String, Int)] = Array((Raisin,4), (Kiwi,2), (Fraise,3), (Orange,6), (Bannane,4))

ExempleExemple

� aggregateByKey est une méthode de la classe PairRDDFunctions.

� il existe deux variantes de cette méthode nécessitant en plus soit le nombre de partitions soit un partitionner.

À retenirÀ retenir

40

M.MICHRAFY

Page 41: Spark RDD : Transformations & Actions

OPÉRATION DE TRANSFORMATION : MÉTHODE SORTBYKEY

� Pour une RDD[(k,v)], sortByKeyretourne une RDD[(k,v)] triée selon unordre prédéfini

� La clé doit implémenter le traitOrdered

ObjectifObjectif

def sortByKey(ascending: Boolean = true, numPartitions: Int = self.partitions.length): RDD[(K, V)]

API : scala, Classe : OrderedRDDFunctions, Package : org.apache.sparkEntrée : ascending boolean indiquant le type de trie

numPartitions, optionnel, indique le nombrede partitions

Sortie : RDD[(K, V)]

SignatureSignature

// créer une rdd de type (k,v)

val x = sc.parallelize(List(("B", 4),("K", 2),("F", 2),("O", 5),("R",4)),3)

// appliquer la méthode sortByKey

val yas = x.sortByKey(true)

val yde = x.sortByKey(false)

// afficher les résultats

yas.collect() // res30: Array[(String, Int)] = Array((B,4), (F,2), (K,2), (O,5), (R,4))

yde.collect() // res32: Array[(String, Int)] = Array((R,4), (O,5), (K,2), (F,2), (B,4))

Exemple 1Exemple 1

� sortByKey est une méthode de la classe OrderedRDDFunctions.

� Par conséquent, la RDD source doit avoir des élements de type (K,V)

À retenirÀ retenir

case class A(tag:String, load:Int) extends Ordered[A] {

def compare( a:A ) = tag.compareTo(a.tag)

}

// créer une rdd de type (k,v)

val xls = List( A("w",50), A("v",2), A("l",7), A("s",6))

val xlsrdd = sc.parallelize(xls,2)

val v = sc.parallelize(1 to 4,2)

val xx = xlsrdd.zip(v)

// appliquer la méthode sortByKey

val yy = xx.sortByKey(true)

// afficher les résultats

yy.collect() // Array[(A, Int)] = Array((A(l,7),3), (A(s,6),4), (A(v,2),2), (A(w,50),1))

Exemple 2Exemple 2

41

M.MICHRAFY

Page 42: Spark RDD : Transformations & Actions

OPÉRATION DE TRANSFORMATION : MÉTHODE JOIN

� La méthode join nécessite des RDDde type (K,V)

� Elle permet de faire une jointure sur laclé entre la RDD source et la RDDpassée en argument.

� La valeur de retour est une RDD detype (K, (V, W))

ObjectifObjectif

def join[W](other: RDD[(K, W)]): RDD[(K, (V, W))]

API : scala, Classe : PairRDDFunctions, Package : org.apache.sparkEntrée : other est une RDD de type (K,W)Sortie : RDD[(K, (V, W))]

SignatureSignature

// créer des rdd de type (k,v)

val l1 = List(("A",1),("B",2),("C",3),("D",5),("E",1))

Val l2 = List(("A",2),("E",2),("C",5),("D",5),("G",1))

val x = sc.parallelize(l1,2) //x: org.apache.spark.rdd.RDD[(String, Int)] = ParallelCollectionRDD[7] at parallelize at <console>:26

val y = sc.parallelize(l2, 2) // y: org.apache.spark.rdd.RDD[(String, Int)] = ParallelCollectionRDD[8] at parallelize at <console>:26

// appliquer la méthode join // z: org.apache.spark.rdd.RDD[(String, (Int, Int))] = MapPartitionsRDD[11] at join at <console>:32

val z = x.join(y)

// afficher les résultats

z.collect() // res1: Array[(String, (Int, Int))] = Array((D,(5,5)), (A,(1,2)), (C,(3,5)), (E,(1,2)))

� il existe deux variantes de cette méthode nécessitant en plus soit le nombre de partitions soit un partitionner.

� il existe aussi une jointure à droite ou à gauche

( voir leftOuterJoin, rightOuterJoin)

À retenirÀ retenir

ExempleExemple

42

M.MICHRAFY

Page 43: Spark RDD : Transformations & Actions

OPÉRATION DE TRANSFORMATION : MÉTHODE CARTESIAN

� La méthode cartesian retourne uneRDD[(K,V)] qui est le produit cartésiende la RDD source et la RDDargument.

� La RDD retournée est de taille nxmavec n, m les nombres d’éléments dela RDD source et la RDD passée enargument.

ObjectifObjectif

def cartesian[U](other: RDD[U])(implicit arg0: ClassTag[U]): RDD[(T, U)]

API : scala, Classe : RDD, Package : org.apache.spark

Entrée : other est une RDD de type USortie : une RDD de type (T,U)

SignatureSignature

// créer deux RDD

val x = sc.parallelize( 1 to 5, 2) // x: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[12] at parallelize at <console>:24

val y = sc.parallelize(List(("A",2),("E",2),("C",5)), 2) // y: org.apache.spark.rdd.RDD[(String, Int)] = ParallelCollectionRDD[13] at parallelize at <console>:24

// calculer le produit cartésien de x et y

val z = x. cartesian(y) // z: org.apache.spark.rdd.RDD[(Int, (String, Int))] = CartesianRDD[14] at cartesian at <console>:28

// évaluer la taille de z // res3: Boolean = true

z.count() == x.count () * y.count()

// afficher les éléments de z // res4: Array[(Int, (String, Int))] = Array((1,(A,2)), (2,(A,2)), (1,(E,2)), (1,(C,5)), (2,(E,2)), (2,(C,5)), (3,(A,2)),

z.collect() // (4,(A,2)), (5,(A,2)), (3,(E,2)), (3,(C,5)), (4,(E,2)), (4,(C,5)), (5,(E,2)), (5,(C,5)))

ExempleExemple

� La RDD retournée est une instance de la classe PairRDDFunctions,

� Pour un élément (k,v) de la RDD retournée, k est un élément de la RDD source et v est un élément de la RDD passée en argument

À retenirÀ retenir

43

M.MICHRAFY

Page 44: Spark RDD : Transformations & Actions

OPÉRATION DE TRANSFORMATION : MÉTHODE COGROUP

� Pour une RDD source (K,V) et uneRDD de type (K,W), la méthodecogroup retourne une RDD detype (K, (Iterable<V>,Iterable<W>)).

ObjectifObjectif

def cogroup[W](other: RDD[(K, W)]): RDD[(K, (Iterable[V], Iterable[W]))]

API : scala, Classe : PairRDDFunctions, Package : org.apache.spark

Entrée : other est une RDD de type (K,W)Sortie : une RDD de type [(K, (Iterable[V], Iterable[W]))

SignatureSignature

// créer deux RDD de type clé-valeur

val x = sc.parallelize(List(("A",1), ("A",2),("C",5), ("D",10),("D",1)), 2)

val y = sc.parallelize(List(("A",3), ("B",3), ("B",6), ,("C",7)), 2)

// regrouper par clé

val z = x. cogroup(y) // RDD[(String, (Iterable[Int], Iterable[Int]))] = MapPartitionsRDD[18] at cogroup at <console>:28// comparer le nombre des clés distinct avec celui du nombre d’éléments de z

x.map(w => w._1).union(y.map(w => w._1)).distinct().count() == z.count() // res5: Boolean = true

// calculer le nombre des éléments de z

z.count() // res6: Long = 4

// afficher les éléments de z

z.collect() // res7: Array[(String, (Iterable[Int], Iterable[Int]))] = Array((B,(CompactBuffer(),CompactBuffer(3, 6))), (D,(CompactBuffer(10,1),CompactBuffer())),

// (A,(CompactBuffer(1, 2),CompactBuffer(3))), (C,(CompactBuffer(5),CompactBuffer(7))))

� Cette méthode a plusieurs variantes :� 2 à 3 arguments de type RDD[(K,W)]� Le nombre de partitions

� Le nombre d’éléments de la RDD obtenue est égal au nombre de clés distinctes dans les deux RDD.

� SI une clé est absente d’une RDD alors sa valeur est remplacé par vide.

À retenirÀ retenir

ExempleExemple

44

M.MICHRAFY

Page 45: Spark RDD : Transformations & Actions

OPÉRATION DE TRANSFORMATION : MÉTHODE COALESCE

� La méthode coalesceregroupe les données de laRDD source dans un nombrede données de partitions.

ObjectifObjectifdef coalesce(numPartitions: Int, shuffle: Boolean = false, partitionCoalescer: Option[PartitionCoalescer] = Option.empty)(implicit ord: Ordering[T] = null): RDD[T]

API : scala, Classe : RDD, Package : org.apache.sparkEntrée : numPartitions le nombre de partitions visé

shuffle pour l’étape de shuffle, par défaut falsepartitionCoalescer optionnel, indique la manière de fusionner les partitions

Sortie : une RDD de type T

SignatureSignature

// créer une RDD avec 50 partitions

val x = sc.parallelize( 1 to 1000, 50) // x: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[25] at parallelize at <console>:24

// appliquer coalesce

val y = x. coalesce(10, true) // y: org.apache.spark.rdd.RDD[Int] = MapPartitionsRDD[29] at coalesce at <console>:26

val z = x.coalesce(3, false) // z: org.apache.spark.rdd.RDD[Int] = CoalescedRDD[30] at coalesce at <console>:26

// afficher les partitions

y. getNumPartitions // res8: Int = 10

z. getNumPartitions // res9: Int = 3

ExempleExemple

� La méthode coalesce est similaire à la méthode repartition

� Elle permet de contrôler le nombre de partitions d’ une RDD

À retenirÀ retenir

45

M.MICHRAFY

Page 46: Spark RDD : Transformations & Actions

OPÉRATION DE TRANSFORMATION : MÉTHODE REPARTITION

� La méthode repartitionregroupe les données de laRDD source dans un nombredonné de partitions.

ObjectifObjectifdef repartition(numPartitions: Int)(implicit ord: Ordering[T] = null): RDD[T]

API : scala, Classe : RDD, Package : org.apache.spark

Entrée : numPartitions le nombre de partitions visé

Sortie : une RDD de type T

SignatureSignature

// créer une RDD avec 50 partitions

val x = sc.parallelize( 1 to 1000, 50) // x: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[31] at parallelize at <console>:24

// appliquer repartition

val y = x. repartition(10) // y: org.apache.spark.rdd.RDD[Int] = MapPartitionsRDD[35] at repartition at <console>:26

// afficher le nombre de partitions

y. getNumPartitions // res10: Int = 10

ExempleExemple

� La méthode repartitionest similaire à la méthode coalesce.

� Cette méthode fait appel à la méthode coalesce avec les deux arguments : numPartitions et shuffle=true

À retenirÀ retenir

46

M.MICHRAFY

Page 47: Spark RDD : Transformations & Actions

OPÉRATION DE TRANSFORMATION : MÉTHODE SAVEASTEXTFILE

� La méthode saveAsTextFileenregistre le contenu de laRDD dans le dossier passé enargument

ObjectifObjectifdef saveAsTextFile(path: String): Unit

API : scala, Classe : RDD, Package : org.apache.spark

Entrée : path le nom fichier

Sortie : pas de valeur de retour (Unit).

SignatureSignature

// créer une RDD avec 50 partitions

val x = sc.parallelize( 1 to 20, 3)

val y = sc.parallelize(List((1,2),(3,5),(6,7),(8,10),(11,15),(18,20)), 2)

// enregistrer les données de la RDD x dans rdd_x

x.saveAsTextFile("rdd_x") // un dossier rdd_x est crée avec des fichiers contenant les données de chaque partition

// enregistrer les données de la RDD y dans rdd_x

y.saveAsTextFile("rdd_x") // Une exception se déclenche puisque le dossier rdd_x existe

ExempleExemple

� saveAsTextFile crée un dossier path et enregistre les données de chaque partition dans un fichier part-0000x où x est un entier.

� Si le dossier path existe alors une exception se déclenche.

À retenirÀ retenir

47

M.MICHRAFY

Page 48: Spark RDD : Transformations & Actions

DR MUSTAPHA MICHRAFY

CONTACT : [email protected]


Recommended