Blog ENI : Toute la veille numérique !
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
💥 Les 22 & 23 novembre : Accès 100% GRATUIT
à la Bibliothèque Numérique ENI. Je m'inscris !

Spark pour l’enrichissement de données

L’API DataFrame

1. Introduction

L’API DataFrame, bien que l’une des plus utilisées aujourd’hui, n’est arrivée que lors de la sortie de la version 1.3 du framework. Avant cela, pour réaliser des traitements de données dans Spark, l’API était RDD. L’API DataFrame est considérée comme haut niveau en comparaison de RDD. Elle permet d’écrire un code plus expressif. Grâce à elle, nous pouvons davantage nous concentrer sur le code métier. Elle est aussi plus performante, car elle contient un moteur d’optimisation.

Avec l’objet DataFrame, vous pouvez réaliser des actions distribuées sur des données. Un DataFrame est associé à de l’information organisée sous forme de colonnes et de lignes. Il comprend différentes fonctions pour créer des transformations sur celles-ci.

Pour rappel, il y a plusieurs manières de créer les objets DataFrame. Nous en avons vu deux. Nous pouvons en créer un de toutes pièces, comme ceci :

from typing import List 
from pyspark.sql import DataFrame 
from pyspark.sql.types import StructType, StructField,  
StringType 
 
data: List = [("Diamant_1A", "TopDiamant", "300"), 
    ("Diamant_2B", "Diamants pour toujours", "45"), 
    ("Diamant_3C", "Mes diamants préférés", "78"), 
    ("Diamant_4D", "Diamants que j'aime", "90"), 
    ("Diamant_5E", "TopDiamant", "89") 
  ] 
 
schema: StructType = StructType([ \ 
    StructField("reference", StringType(), True), \ 
    StructField("marque", StringType(), True), \ 
    StructField("prix", StringType(), True) 
  ]) 
 
dataframe: DataFrame =  
spark.createDataFrame(data=data,schema=schema) 
 
dataframe.show(truncate=False) 

Il est aussi possible de générer un DataFrame en lisant un fichier ou en se connectant à un environnement externe. Par exemple :

dataframe: DataFrame =  
spark.read.format("csv").load("chemin/vers/mon/fichier")...

L’API SQL

1. Principes de l’API SQL

a. Intérêts de l’API SQL

L’API SQL permet de reproduire les mêmes actions que l’API DataFrame, mais sous une forme syntaxique différente. Le principe est d’utiliser la structure SQL pour transformer les données. C’est une API qui comporte son lot d’avantages et d’inconvénients. Le premier atout est que la plupart des développeuses et développeurs connaissent SQL. Si vous êtes dans ce cas, il vous est peut-être plus facile de passer par cette API que de passer par d’autres API Spark moins familières. Autre avantage fort appréciable : l’API SQL peut permettre à des gens qui ne connaîtraient que SQL de faire une analyse de données avec un appel SQL. Nous avons travaillé sur un projet qui permettait aux utilisateurs et utilisatrices du service de faire cela. Une plateforme web aidait à construire des requêtes. Elles étaient exécutées sur le lac de données. Si le résultat était celui escompté, après vérification des performances, les demandes étaient automatiquement intégrées dans un projet Spark.

L’API SQL a aussi des inconvénients. SQL est un langage déclaratif, contrairement à Python qui est un langage de programmation impérative. Cela signifie que votre code SQL reflète le résultat attendu. L’abstraction déclarative de SQL est confortable pour de nombreuses situations, mais aussi plus complexe à déboguer parce que vous n’avez pas accès aussi facilement aux détails d’implémentation. C’est encore plus vrai quand un long programme alambiqué a été pensé avec l’API SQL de Spark. La syntaxe de cette dernière étant finalement faite de chaînes de caractères, vous pouvez séparer les différentes parties d’une même requête et vous retrouver alors avec la sélection quelque part dans un fichier et la clause FROM beaucoup plus loin dans un autre. Cela peut paraître commode pour mutualiser des portions de code et, dans une certaine mesure, cela l’est sans doute. Cependant, c’est aussi une technique à utiliser avec...

L’API Dataset

1. Principes et intérêts

L’API Dataset est un peu à part. Elle permet d’opérer des actions réalisables via les API DataFrame et SQL. Cependant, elle n’est pas capable de le faire avec les mêmes performances. Elle reste cependant plus performante que l’API RDD que nous verrons à la section RDD, l’API bas niveau.

La particularité de l’API Dataset, c’est qu’elle est typée. Cela signifie qu’au lieu de recevoir vos erreurs lorsque le programme est lancé, vous les recevez quand il est compilé. Nous venons d’évoquer là la raison pour laquelle cette API n’est pas disponible avec les langages Python ou R. Elle aurait moins d’intérêt puisque ces deux derniers sont interprétés. Pas de compilation, pas d’API Dataset. C’est pourquoi pour ce chapitre, nous basculons en Scala, originellement le premier langage de Spark.

Avec l’API Dataset, vous pouvez faire de nombreuses choses, mais vous n’avez pas autant d’aide qu’avec les API DataFrame ou SQL. Il vous faudra coder beaucoup de fonctionnalités vous-même. C’est l’un des inconvénients de l’API en plus de ses performances moindres. Les avantages, c’est que nous avons un programme plus sécurisé. Les erreurs sont remontées plus tôt. Nous basculons aussi dans un mode de programmation plus impératif. L’API DataFrame et surtout l’API SQL sont plutôt déclaratives. Nous indiquons le résultat que nous voulons voir apparaître. Avec l’API Dataset, c’est à nous d’indiquer ce que nous souhaitons obtenir.

2. Création

a. À partir d’une séquence

Un objet Dataset peut se créer de différentes manières. Nous pouvons parvenir à cela à partir d’une séquence. Ce dernier concept correspond à une liste dans le langage Python. Puisque l’API Dataset est typée, nous commençons par créer une classe.

Pour cela, utilisons l’élément case class de Scala, comme suit :

case class Diamant( 
  reference: String, 
  marque: String, 
  prix: Int, 
  couleur: String 
) 

En Scala, nous...

Les jointures de données

1. Introduction

Nous avons vu la manière dont Spark prend des données en entrée, en tire parti, puis les transfère dans un autre système. Cet enrichissement de données ne saurait être complet sans les jointures, autrement dit sans la capacité à joindre plusieurs objets DataFrame ou Dataset. Vous y aurez souvent recours. Le principe repose sur l’idée que nous avons différentes sources de données et qu’en les joignant à l’aide d’une ou de plusieurs clés communes, nous en tirons davantage d’informations.

Prenons un exemple. Dans le monde de la mode vestimentaire, il y a des couleurs considérées comme tendance. Nous pouvons attribuer un score à chaque coloris. Plus la note est haute, plus la couleur est à la mode. En parallèle, nous avons des ventes de diamants qui ont tous un pigment. La question qui se pose est la suivante : la mode vestimentaire influence-t-elle les achats de nos bijoux ? Pour tenter d’y répondre, nous joignons les deux sources de données et comptons le nombre de pierres vendues par couleur. Construisons dans un premier temps nos deux DataFrame.

Pour la suite des exemples, l’API DataFrame sera utilisée, même si nous verrons aussi quelques morceaux de code écrits à partir des API SQL et Dataset.

Nous commençons par les diamants :

from typing import List 
from pyspark.sql import DataFrame 
from pyspark.sql.types import StructType, StructField,  
StringType, IntegerType 
 
data: List = [("Diamant_1A", 300, "jaune"), 
    ("Diamant_2B", 45, "gris"), 
    ("Diamant_3C", 78, "gris"), 
    ("Diamant_4D", 90, "jaune"), 
    ("Diamant_5E", 89, "violet"), 
    ("Diamant_6F", 500, "violet"), 
    ("Diamant_7G", 250, "gris"), 
    ("Diamant_8H", 20, "jaune"), 
  ] 
 
schema: StructType = StructType([ \ 
    StructField("reference", StringType(), True), \ 
    StructField("quantite_vendue"...

RDD, l’API bas niveau

1. Présentation générale

a. L’histoire

L’API RDD est une API dite bas niveau. Elle correspond aussi au composant nommé Spark Core.

images/02EP05.png

L’API RDD dans les composants Spark

Elle est la première à avoir été développée dans l’outil Spark. C’est une des raisons pour lesquelles vous en entendrez beaucoup parler. Vous trouverez encore des exemples de code sur la Toile dans cette API, mais de moins en moins cela dit, car elle tend à être moins utilisée. Il n’y a que peu d’intérêt à commencer par développer dans cette API dans un nouveau projet. Cependant, il faut savoir que derrière les API haut niveau (DataFrame, Dataset, SQL) se cache toujours l’API RDD. Toutes les transformations et actions que nous développons dans les API haut niveau sont transpilées dans l’API RDD. C’est souvent par là que vous serez amené à déboguer votre code. C’est pourquoi avoir une compréhension minimale de cette API est important.

b. Caractérisation des RDD

Commençons par caractériser les objets RDD. Comme un DataFrame ou un Dataset, il s’agit d’un composant visant à contenir un ensemble de données. C’est à travers lui que vous réalisez des transformations et des actions. Vous avez donc les mêmes concepts à l’œuvre. Ici aussi, les transformations ne s’effectuent réellement que lorsque l’action est déclenchée.

Un objet RDD représente un objet Python. Il s’agit en fait d’une API typée. Ce n’est pas très pertinent pour le langage Python, mais ça l’est pour Scala ou Java. En réalité, il y a deux types de RDD : les RDD génériques et les RDD sous la forme clé/valeur. Les deux ont leur utilité.

Dans cette API, il n’y a pas de notion de lignes ou de colonnes, comme dans les API haut niveau. RDD est une API où il faut construire presque tout soi-même. Si vous découvrez Spark, vous ne devez absolument pas commencer par celle-ci, mais plutôt vous concentrer d’abord sur les API haut niveau.

De plus, la performance des objets RDD n’est pas au rendez-vous. Il n’y...

L’API Spark streaming

1. Introduction

a. Streaming versus batch

Dans le monde des données, il y a deux manières d’accomplir des traitements. La première consiste à travailler avec un lot d’informations. À partir de celles-ci, nous réalisons des analyses ou des transformations de manière ponctuelle. En informatique, on a l’habitude de parler de batch. En batch, d’importants lots de données sont consommés et renvoyés. Supposons que vous voulez prédire les prix des diamants qui sont mis en vente sur la Toile. Les tarifs sont généralement modifiés une fois par jour. Dans un tel cas, vous pouvez envisager d’effectuer les prédictions durant la nuit. De cette manière, elles seront prêtes le lendemain. Vous opérez cela sur l’ensemble de vos données. Vous travaillez sur la totalité des sites marchands de diamants. Il s’agit donc d’un lot de produits conséquent. Les transformations et prédictions sont effectuées en une fois. Cette manière de faire, appelée batch, est celle que nous avons étudiée jusqu’ici.

À présent, intéressons-nous à une autre manière de traiter les données : le mode streaming, aussi appelé flux ou diffusion en continu. Ce principe désigne la lecture, le traitement et l’écriture de données en continu. Dans ce mode, vous ne traitez pas toutes les informations en une fois, mais une à une. Par exemple, toutes les fois où un site marchand affiche un nouveau prix pour un diamant, vous vérifiez que ce tarif n’est pas aberrant. C’est une forme de détection d’anomalies. Si vous voulez faire de la détection dès qu’un tarif est mis à jour, vous basculez dans le mode streaming où chaque données est traitée dès son apparition. Nous pouvons dire que les informations sont consommées en direct. On parle aussi de temps réel, une expression que nous allons réutiliser.

Il n’y a pas de bon ou de mauvais mode. Le batch est utile pour certaines situations, le streaming pour d’autres. Voyons les avantages et inconvénients de chacun.

Le mode batch est utile quand vous travaillez sur de larges volumes...