On distingue classiquement deux grandes catégories de données :
<!--
<note>
Parfois, la distinction entre quantitatif et qualitatif n’est pas nette:
* Possibilité d’ordonner les chaînes de caractères (de type nom/prénom) par ordre alphabétique
* On peut “traduire” une chaîne de caractères en entier (son code ASCII)
* Les valeurs logiques vrai/faux sont souvent traduites en valeurs “entières” 1/0
* Plus subtil : il est possible de définir des ordres partiels, des hiérarchies sur des données qualitatives :
* regroupement par secteur géographique
* notion de distance (géographique et temporelle) entre catégories
* Inversement, il est possible de rendre qualitatif des données quantitatives en réalisant des classes. Exemple : tranches d’âge 0-25/25-35/35-55/+55, mineur/majeur, recalé/passable/AB/B/TB etc...
</note>
--!>
Une valeur numérique (digitale) consiste en:
<!--
<note>
**Types de données standards**
Les principaux types de données SQL sont les suivants :
* ''CHAR (longueur)'' : Ce type de données permet de stocker des chaînes de caractères de longueur fixe. ''longueur'' doit être inférieur à 255, sa valeur par défaut est 1.
* ''VARCHAR(longueur)'' : Ce type de données permet de stocker des chaînes de caractères de longueur variable. ''longueur'' doit être inférieur à 2000, il n'y a pas de valeur par défaut.
* ''TEXT'' : un texte de longueur quelconque
* ''INTEGER'' : entier (codage classique su 4 octets)
* ''NUMBER(longueur)'' : entier naturel, ''longueur'' précise le nombre maximum de chiffres significatifs stockés
* ''DECIMAL (longueur,[précision])'' : Le type de données decimal peut stocker jusqu'à 38 chiffres pouvant tous se trouver à droite de la virgule décimale. Il stocke une représentation exacte du nombre décimal, sans aucune approximation de la valeur stockée. ''longueur'' précise le nombre maximum de chiffres significatifs stockés (par défaut 38), ''précision'' donne le nombre maximum de chiffres après la virgule (par défaut 38), sa valeur peut être comprise entre -84 et 127. Une valeur négative signifie que le nombre est arrondi à gauche de la virgule.
* ''FLOAT'' : nombre à virgule flottante simple précision
* ''DOUBLE'' : nombre à virgule flottante double précision
* ''DATE'' : ce type de données permet de stocker des valeurs de type date. Format : '''2005-12-12''' (12 décembre 2005)
* ''TIME'' : ce type de données permet de stocker des valeurs de type heure. Format : '''10:45:02''' (10 h 45 min 2 s)
* ''DATETIME'' : donnée de type date-heure. Format : '''2005-12-12 10:45:02''' (12 décembre 2005, 10 h 45 m 02 s)
* ''TIMESTAMP'' : donnée de type date-heure (correspond à un stockage plus ‘compact’ que le type ''DATETIME'')
</note>
-->
x = 'a'
x
une variable de type caractèrea
la valeur numérique (encodé):code = ord('/') print(code)
47
(le code ASCII du caractère '/
') '😃
' appartient à la norme utf-8. Pour obtenir la valeur entière correspondante :code = ord('😃') print(code)
print(chr(233)) print(chr(119070))
Chaîne de caractère :
s = "bonjour"
s
est une variable"bonjour"
est une séquence de caractères for c in s : print (c)
Affiche :
b o n j o u r
Le programme affiche les caractère 1 par 1, c’est une "chaîne" de plusieurs caractères individuels.
Donnée texte
Un texte, au même titre qu'un mot, est une chaîne de caractères (dont la longueur est définie par la longueur de la séquence de caractères qui définissent le texte, ponctuations, espaces et caractères de retour à la ligne compris).
Par définition les caractères séparateurs définissent la taille des espaces entre les mots, ainsi que les passages à la ligne lors de l'affichage du texte.
""
: caractère nul " "
: un espace simple"\t"
: tabulation"\n"
: passage à la ligne ("retour chariot")"\b"
: retour arrière ("backspace")Codage du texte
L'ensemble des messages possibles peut être réduit à l'ensemble des entiers naturels. En effet, chaque caractère d'un texte peut être traduit en entier en interprétant le code binaire correspondant comme un entier.
Pour traduire une chaîne de caractères en entier, il faut "construire un nombre" à partir de chaque caractère de la chaîne en prenant en compte sa position.
encode
qui effectue une telle traductions = 'paul.poitevin@centrale-marseille.fr' b = s.encode()
Un nombre en base 256 est difficile à lire et interpréter. On le traduit en base 10 :
i = int.from_bytes(b, byteorder='big') print("i =", i)
Ce qui donne :
i = 852806586114976881510056778471769180697471859150728801241505293627173168229624211058
Un document texte pourra être décrit soit comme :
Recherche simple
d
: document de taille m
On cherche un algorithme qui retourne toutes les occurrences (position dans le doc) d’un certain terme t
(de taille k<m
)
t = "ami"
d
:
"Les amis de mes amis sont mes amis." ^ ^ ^ 4 16 30
on note d
le texte et t
le motif recherché dans le texte
Algo : recherche_simple Données : d, t : chaînes de caractères Début n = len (d) m = len (t) i <-- 0 tant que i < n - m: j <-- 0 tant que j < m et d[i+j] = t[j] : j += 1 si j == m : retourner i sinon : i <-- i + 1 Fin
Remarque : Il peut être nécessaire de vérifier que le terme est précédé et suivi par les caractères d’espacement pour éviter de détecter les mots dont le mot recherché est préfixe ou suffixe.
Cette approche a un inconvénient : après une comparaison infructueuse, la comparaison suivante débutera à la position i + 1, sans tenir aucun compte de celles qui ont déjà eu lieu à l'itération précédente, à la position i.
Algorithme de Knuth-Morris-Pratt
L'algorithme de Knuth-Morris-Pratt examine d'abord la chaîne t
et en déduit des informations permettant de ne pas comparer chaque caractère plus d'une fois.
c
appartient au motif t
en temps constantt
.i = m - 1
d
de i
à i - m
décroissant, et on s'arrête au premier caractère commun (i.e. j
⇐ i
t.q. d[i-j]
appartient à t
)c
= d[i-j]
le caractère communk
la position de la dernière occurrence de c
dans t[:m-j-1]
m - 1 - j - k
m
RECHERCHE DE CHAINES CODEES EN MACHINE CHINE CHINE CHINE CHINE CHINE CHINE CHINE CHINE CHINE CHINE RECHERCHE DE CHAINES CODEES EN MACHINE
Algo : recherche améliorée (Knuth-Morris-Pratt) Données : d, t : chaînes de caractères Début: n = len (d) m = len (t) i <-- m - 1 tant que i < n : # PRE-TRAITEMENT j <-- 0 tant que j < m - 1: c = d[i - j] si c appartient à t[:m-j-1] k <-- dernière_occurrence(c, t[:m-j-1]) decalage <-- m - 1 - j - k break sinon j += 1 si j == m - 1: decalage <-- m # TRAITEMENT j <-- 0 tant que j < m : si t[m - j - 1] = d[i - j] j += 1 sinon break si j = m: retourner i - m + 1 # DECALAGE i <-- i + decalage retourner -1 Fin
Lecture séquentielle des caractères :
"Les amis de mes amis sont mes amis." ^ position initiale de la tête de lecture
{a,à,ä,b,c,ç,d,e,é,è,ê,ë,...,z,A,B,C,...,Z,1,2,3,...,0}
{!,#,$,%,&,",',...}
remarque : pour extraire la liste des mots présents dans le texte, on doit identifier les débuts et les fins de mots :
Algo : compte-mots Données : - d : chaîne de caractères Début: nb_mots <-- 0 sep <-- Vrai pour tout c dans d: si sep est Vrai et c est alphanumérique: sep <-- Faux nb_mots <-- nb_mots + 1 sinon si sep est Faux et c est séparateur: sep <-- Vrai retourner nb_mots Fin
Code équivalent : compter les mots à l'aide d'un automate fini:
def compte_mots(d): state = 0 cpt = 0 for i in range(len(d)): if state == 0 and is_alpha(d[i]): state = 1 cpt += 1 if state == 1 and is_sep(d[i]): state = 0 return cpt
Présentation: un automate fini décrit les différentes étapes d'un calcul sous la forme d'un graphe orienté.
Pour réaliser des calculs, on a besoin d'opérandes. Les opérandes sont lus séquentiellement en entrée de l'automate. Ils obéissent à un certain alphabet (ou ensemble de symboles, …) Σ.
Enfin, des résultats de calcul sont produits en sortie de l'automate.
Plus concrètement, à chaque symbole lu en entrée, l'automate consulte une table des symboles acceptés à partir de l'état courant. Si le symbole est accepté, l'automate effectue la transition d'état, et produit une sortie (par exemple incrémenter le compteur de mots). Dans le cas contraire, il s'arrête.
Définition:
Un automate fini est défini par :
L'état initial et la séquence des symboles lus définit la séquence de symboles produits en sortie (le résultat du calcul)
La famille des automates finis définit une classe de calculs (l'ensemble des calculs réalisables par des automates finis):
Mais pas :
remarque: il existe des automates de calcul plus puissants :
permettant d'implémenter des calculs plus complexes
De manière plus générale recherche d’expressions peut être effectuée à l’aide d’automates finis non déterministes.
Remarque : pour tout automate fini non déterministe A, il existe un automate fini déterministe A′ qui reconnait le même langage (plus compliqué à écrire).
Représentation graphique :
Lecture séquentielle des caractères :
"Les amis de mes amis sont mes amis." ^ position initiale de la tête de lecture
L'automate doit reconnaître les mots suivants :
ab bab abab bbab aabab abbab babab bbbab aaabab etc..
Exemples:
+4
, -455
, 1024
, 0
Remarques :
re
Traduction de l'automate non déterministe précédent sous forme d'expression régulière :
[ab]*ab
Remarque : les langages qui peuvent être reconnus par des expressions régulières sont appelés les langages réguliers.
Exemples de langages non réguliers:
Définition : Il s’agit d’une syntaxe “condensée” de description d’automates finis permettant de reconnaître des motifs dans un texte.
En Python, les expressions régulières sont implémentées dans la librairie re
import re d = "Les astronautes de la mission Gemini 8 sont désignés le 20 septembre 1965 : Armstrong est le commandant et David Scott le pilote. Ce dernier est le premier membre du groupe d'astronautes à recevoir une place dans l'équipage titulaire d'une mission spatiale. La mission est lancée le 16 mars 1966. Celle-ci est la plus complexe réalisée jusque-là, avec un rendez-vous et un amarrage du vaisseau Gemini avec l'étage de fusée Agena et une activité extravéhiculaire (EVA) qui constitue la deuxième sortie américaine et la troisième en tout, réalisée par Scott. La mission doit durer 75 heures et le vaisseau doit effectuer 55 orbites. Après le lancement de l'étage-cible Agena à 15 h 00 UTC, la fusée Titan II GLV transportant Armstrong et Scott décolle à 16 h 41 UTC. Une fois en orbite, la poursuite de l'étage Agena par le vaisseau Gemini 8 s'engage." liste_termes = re.findall(r"([1-9]\d*|0)", d)
a
: le caractère a[ab]
: le caractère a ou le caractère b[a-z]
: n'importe quel caractère minuscule entre a et z[^a]
: n'importe quel caractère sauf le caractère a
: le caractère espace\n
: le caractère "passage à la ligne".
: n'importe quel caractère\.
: le caractère "." uniquement[1-9]
: un chiffre entre 1 et 9\w
: n'importe quel caractère alphanumérique \s
: n'importe quel caractère d'espacement\d
: n'importe quel chiffreDef : une expression est définie comme une suite de transition. Le mot est accepté lorsque la suite de transitions est respectée
Exemple :
r"chal[eu]t"
accepte chalet et chalut
r"\w\w\w"
accepte tous les mots de 3 lettres
Branchements et Récursion
(artichaud)
(chien|chat)
*
: le caractère ou l'expression précédente répété entre 0 et n fois+
: le caractère ou l'expression précédente répété entre 1 et n fois?
: le caractère ou l'expression précédente répété entre 0 et 1 foisr'\w[\.\w\-]*\w@\w[\.\w\-]*\.\w\w\w?'
Un algorithme de complétion est un mécanisme logique permettant d'anticiper la saisie et de proposer des mots automatiquement pour faciliter les recherches dans un formulaire sur une page web par exemple.
On utilise pour cela une structure de données arborescente, où chaque nœud de l'arbre est une étape de lecture et chaque arête correspond à la lecture d'une lettre. Les nœuds sont indexés par les lettres suivantes possibles du mot, avec un compteur par nœud pour savoir si celui-ci est final ou non (le nœud est final si le compteur est >0).
On commence par construire un arbre de complétion à partir de mots de vocabulaire,
L'arbre construit de cette manière est très large mais peu profond :
Une fois l'arbre construit, on l'utilise pour compléter un début de mot proposé par l'utilisateur (souvent plusieurs complétions possibles).
Exemple :
ar
{art, arbre}
On cherche à exprimer une distance entre deux chaînes de caractères. Une distance entre 2 textes d1 et d2 est telle que :
La distance de Hamming entre deux chaînes de même taille est définie comme le nombre de caractères non appariés. Ainsi la distance de Hamming entre "passoire" et "pastèque" est égale à 4.
Exemple :
p a s s o i r e | | | x x x x | p a s t e q u e
distance = 4
Peut-on généraliser cette distance à des chaînes de taille différente?
La distance d’édition est définie, pour deux chaînes de longueur quelconque, comme le nombre minimal d’opérations permettent de transformer d1 en d2, avec les opérations suivantes :
Il existe différentes manières de transformer la chaîne d1 en d2. On peut par exemple supprimer tous les caractères de d1 et insérer tous les caractères de d2, mais c'est rarement le nombre d'opérations optimal (|d1|+|d2|).
- r o b - e v | ^ | v | a r - b r e
dist = 3
r o b - e x | x v | p o r t e
dist = 3
a - r b r e x v | x ^ | p o r t - e
dist = 4
La résolution de ce problème repose sur les principes de la programmation dynamique.
Un problème d'optimisation combinatoire se caractérise par :
Le nombre de solutions possibles à un problème d'optimisation combinatoire croît exponentielleemnt avec la taille du problème. Trouver une solution par énumération à un tel problème devient rapidement impossible pour des problèmes de taille modérée.
Certains problèmes d'OC peuvent être résolus selon le principe de la programmation dynamique qui consiste à décomposer le problème en sous-problèmes (et en sous-solutions):
Dans le cas de l'appariement de chaîne:
En pratique:
Préparation
variables globales : d1, d2 : chaînes de caractères m = |d1| n = |d2|
Récursif!!
algo : distance données : i, j : etape de calcul début si i = m et j = n : retourner 0 sinon si i = m : retourner dist(i, j+1) + 1 sinon si j = n : retourner dist(i + 1, j) + 1 sinon si d1[i] = d2[j] : retourner min(dist(i, j+1) + 1, dist(i + 1, j) + 1, dist(i + 1, j + 1)) sinon retourner min(dist(i, j+1) + 1, dist(i + 1, j) + 1, dist(i + 1, j + 1) + 1) fin
Dans le cadre de ce cours, nous aborderons :
Les principaux formats d'échange de données sont :
Exemples :
La conservation des données repose principalement sur la structure de stockage,
Un jeu de valeurs encodé et stocké sur un support informatique est appelé un “enregistrement”,
Encodage binaire :
Encodage textuel :
Un bloc de données correspond à une série d’enregistrements obéissant au même format:
La structure de base servant à stocker à une série d’enregistrements est le tableau de données à 2 dimensions :
Structure sous-jacente : tableau à 2 dimensions (ou matrice de données)
Un bloc de données obéit formellement à une structure de type tableau statique:
T
, la position des cases reste fixe au cours de l'utilisation :T[i]
désigne toujours la mếme zone mémoireT[i]
ne désigne pas toujours la mếme zone mémoireLes mémoires informatiques sont des structures statiques. Une fois les données sauvegardées sur le disque, il est difficile d’insérer ou de supprimer des éléments.
La difficulté consiste à définir une organisation logique du tableau permettant de gérer efficacement un tel ensemble (qui peut être de grande taille) :
On parle de structure de stockage. Une telle structure doit permettre :
On considère un ensemble de k
données stockés dans un tableau de données statique T
de N
cases (avec 0
≤k
≤ N
).
Remarques :
0
à N-1
i
est un indice de case, T[i]
désigne le contenu de la caseN
est fixé mais k
varie en fonction du nombre de données stockées
Propriété : les données sont stockés dans les k
premières cases du tableau. Ainsi, les cases de 0
à k-1
sont occupées et l'indice k
désigne la première case libre.
Opérations fondamentales :
On conserve une table des cases libres
B=0010010100100.....01n−1
Stratégies d’allocation
Stratégie par bloc: on alloue des blocs composés de plusieurs cases (S’il existe des blocs libres consécutifs, ils sont fusionnés en un seul)
On souhaite :
Écrire un algorithme permettant d'insérer une donnée d de taille m dans le premier bloc libre disponible (pensez à mettre à jour la table d'allocation B).
Autre stratégie (allocation rapide): On alloue des blocs de 1,2,4,8,…2K pages. Pour une taille donnée 2i-1 < n < 2i, on commence par chercher les blocs de taille 2i, puis 2i+1, … jusqu’à 2K , en divisant ces blocs le cas échéant.
Problème des stratégies par bloc: s’il y a trop de données, on obtient des blocs de taille 1 –> nécessité de réorganiser (défragmenter)
La mémoire secondaire n’est pas directement accessible (les programmes n’ont pas la possibilité d’aller écrire directement sur le disque). Le système d’exploitation assure ainsi l’indépendance du programme par rapport à l’emplacement des données, au travers d’instructions d’entrée/sortie spécialisées.
Pour que les programmes puissent écrire sur le disque, on introduit des objets intermédiaires : les fichiers. Un fichier est caractérisé par (nom, emplacement (volume, arborescence), droit d’accès, taille,…). Il s’agit d’une entité logique. Tout programme utilisant un fichier passe par le système d’exploitation qui, à partir des informations, détermine la localisation des données sur le support.
Le volume est le support sur lequel sont enregistrées les données. On parle de mémoire secondaire (Disque dur, disquette,CD-ROM, etc…). Un volume est divisé en pistes concentriques numérotées de 0 à n ( par ex n = 1024). Chaque piste supporte plusieurs enregistrements physiques appelés secteurs, de taille constante (1 secteur = 1 page).
Page (ou secteur)
Les pages sont les unités de base pour la lecture et l'écriture. une page est une zone contiguë de la mémoire secondaire qui peut être chargée en mémoire centrale en une opération de lecture. Taille standard : une page = 1-2 ko.
La mémoire secondaire est donc organisée comme un tableau de pages : (T[0],…,T[L-1]), où L est le nombre de pages. Chaque page fait m octets. Chaque page peut être libre ou occupée.
Répertoires Chaque volume possède un numéro appelé le label du volume. Tous les descripteurs de fichiers sont regroupés dans une table des matières appelée Répertoire (Directory).
Remarque : cette table des matières est en fait un fichier dont le descripteur est contenu dans le label du volume.
Organisation hiérarchique :
Méthode traditionnelle pour le traitement de fichiers de petite taille. La consultation des données nécessite d’ouvrir une “communication” entre le programme et les fichiers. Ce canal de communication permet de recevoir un flux de données.
Pour établir la communication, il faut connaître : le “chemin d’accès” aux données (disque dur local) l’”adresse” des données (lorsqu’il s’agit de données stockées sur un serveur distant)
L’opération d’ouverture de fichier initialise un descripteur de fichier, qui sert à désigner (dans le programme) le fichier sur lequel on travaille, et d’accéder au contenu du flux.
Ouverture simple:
f = open('/chemin/vers/mon/fichier.dat','r')
Le deuxième argument représente le mode d’ouverture, ici ’r’ représente une ouverture en mode lecture.
Il est important de vérifier que cette opération d’ouverture s’effectue correctement avant de poursuivre le programme (nombreuses possibilités d’erreur : fichier effacé, erreur de nom, pas de droits de lecture,…).
On utilise une instruction de test spécifique pour vérifier que l’ouverture du fichier s’est correctement effectuée, de type try
…catch
… (essaye … sinon …) permettant de prévoir une action de secours lorsqu’une une opération “risquée” échoue.
try : f = open('/chemin/vers/mon/fichier.dat','r') except IOError: print "Erreur d'ouverture!"
Lorsque l’opération d’ouverture est réalisée avec succès, le flux de données devient accessible en lecture (les premières lignes du fichier sont chargées en mémoire et une tête de lecture se positionne sur le premier caractère de la première ligne). Il ne reste plus qu’à lire les données.
La consultation des données s’effectue séquentiellement à l’aide de l’opérateur de lecture readline
. Chaque appel à cet opérateur charge les nouvelles données et déplace la tête de lecture vers les données suivantes. Cette opération peut être effectuée plusieurs fois jusqu’à atteindre la fin de fichier.
Remarque : Lecture/Ecriture
Les opérateurs lire_ligne (readline) et écrire_ligne (write) ne travaillent pas directement sur les données du fichier. Les données du fichier sont chargées en mémoire centrale dans une mémoire “tampon”. L’objet f servant à décrire le fichier a comme attributs :
Lors des opération de lecture, la mémoire tampon est mise à jour au fur et à mesure qu’on avance dans la lecture du fichier par des opérations de lecture sur le disque. En général, plusieurs pages sont chargées en avance. Lors d’une opération d’écriture, la mémoire tampon reçoit les nouvelles données à écrire. Ces données sont effectivement écrites sur le disque lorsque le tampon est suffisamment rempli ou lors de l’opération de fermeture. Au moment de l’écriture effective, le système d’exploitation fait appel à un opérateur d’allocation pour choisir le “meilleur” bloc où stocker les données.
Si on suppose que les données sont rangées sous la forme d’un tableau de lignes, chaque opération de lecture consiste à consulter une ligne du tableau, et à positionner la tête de lecture sur la ligne suivante.
1. Lecture d’une ligne unique :
Python
s = f.readline()
2. Lecture de toutes les lignes (la lecture s’effectue dans une boucle) + affichage de la ligne:
Python
for s in f : print s
L’opération de sauvegarde des données est l’opération complémentaire de la lecture. De nouvelles données doivent être enregistrées sur le disque dur en vue d’une consultation future. Le format de sauvegarde peut être de type texte ou de type binaire. Nous présentons ici la sauvegarde des données dans des formats texte.
Comme dans le cas de l’opération de lecture, il faut au préalable définir dans le programme un descripteur de fichier servant de point d’entrée pour les opération d’écriture. On effectue ce qu’on appelle une ouverture en mode “écriture”.
Python
try : f = open('monfichier.dat','w') except IOError: print "Erreur d'ouverture!!"
On notera qu’il existe en python (ainsi qu’en C, C++, …) plusieurs modes d’ouverture exprimés par le deuxième argument de la fonction open. On retiendra le mode ‘w’ (création d’un nouveau fichier vide) et le mode ‘a’ (ajout de nouvelles données à la suite d’un fichier déjà existant).
La sauvegarde dans le fichier s’effectue à l’aide d’un opérateur d’écriture. Dans le cas des chaînes de caractères, l’opérateur d’écriture sauvegarde ces données à la suite des données déjà écrites.
Python
f.write("Bonjour!\n")
La sauvegarde de données nécessite d’effectuer un choix sur le mode d’encodage, obéissant en général à une norme bien précise (csv, json, xml, etc…). Voir section 1.3.
Une fois les opérations de lecture ou d’écriture terminées, il est nécessaire de fermer le fichier. L’opération de fermeture assure que les données sont effectivement enregistrées sur le disque (et non simplement stockées dans la mémoire tampon - voir section XXX).
Voir aussi :
Une donnée informatique est un élément d'information ayant subi un encodage numérique
Pour une gestion efficace des données, il est nécessaire de pouvoir identifier chaque enregistrement de façon unique.
L'indexation des données repose sur un principe simple d'étiquetage consistant à attribuer une étiquette différente à chaque enregistrement. Cette étiquette peut être une suite de caractères arbitraires, un entier, ou un descripteur explicite. On parle en général de clé ou d'identifiant pour désigner cette étiquette.
On peut représenter l'opération d'indexation sous la forme d'une fonction. Si d est le jeu de valeurs, k(d) désigne l'identifiant de ce jeu de valeurs.
L'indexation suppose l'existence d'une bijection entre l'ensemble des données et l'ensemble des clés, permettant d'assurer l'unité et la spécificité de la clé
L'existence d'un identifiant unique pour chaque jeu de valeurs d permet la mise en œuvre d'une recherche par identifiant (ou recherche par clé).
La recherche par identifiant repose sur une fonction d'adressage I qui à tout identifiant k associe sa position (entrée) i dans un tableau de données: I:k→i. Ainsi si k est l'identifiant servant à la recherche, l'extraction des informations se fait en 2 étapes:
L'identifiant doit en pratique tenir sur un nombre d'octets le plus petit possible pour que la liste L puisse être manipulée en mémoire centrale. Autrement dit, il faut que :
pour que :
Définir un ordre sur les données
La présence d'un identifiant permet de définir un ordre total sur les données :
Lier les données
Dans le cas des bases de données, l'identifiant constitue une référence vers les jeux de valeurs des tableaux de données. Une référence permet de lier les données d'une table aux données d'une autre table.
Exemple :
Structure d'ensemble
L'index définit l'appartenance d'une donnée à un ensemble.
Soit E un ensemble de données indexées : E={d1,d2,...,dK} On a l'équivalence : d∈E⇔k(d)∈I
Ainsi, il ne peut y avoir de doublon car ∀d :
L'exemple le plus simple d'indexation est celui fourni par les numéros de case d'un tableau.
Dans le cas général, l'identifiant n'est pas égal à l'entrée!
On sépare donc l'index k de l'entrée i:
Il existe différentes méthodes permettant d'assurer l'intégrité de l'index:
Utilisation d'une fonction de hachage :
Attribution d'un identifiant arbitraire entre 0 et n-1
i = int.from_bytes(d, byteorder='big')
s = 'paul.poitevin@centrale-marseille.fr' d = bytes(s, 'ascii') i = int.from_bytes(d, byteorder='big') print("i =", i)
donne :
i = 852806586114976881510056778471769180697471859150728801241505293627173168229624211058
k = H(i) = i mod n
j = i + 1
, H(j) = H(i) + 1
(presque toujours)paul.poitevin@centrale-marseille.fr
) = 1697539698
martin.mollo@centrale-marseille.fr
) = 1697539698
paul.poitevin@centrale-marseille.fr
) = 36148249469507
martin.mollo@centrale-marseille.fr
) = 65330032132071
k = H(i) = (i * m) mod n
j = i + 1
, j * m - i * m = m
i * m
peut etre coûteux à calculerj != i
tel que H(i) = H(j)
. Le gestionnaire de bases de données MongoDB utilise une indexation des données par clé cryptographique.
Que faire lorsque l'index ne tient pas en totalité dans la mémoire centrale ?
Considérons un index composé de couples (clé, numero de page). On suppose que l’index est également découpé en pages, chaque page d'index contenant au maximum b clés. Si l’index comporte beaucoup de pages, il est intéressant de l’organiser hiérarchiquement en pages et sous-pages, selon une organisation appelée "B-arbre" (Balanced Tree):
I ← charger la racine de l’arbre tant que I n’est pas une feuille : k’ ← première clé de I tant que k > k’ k’ ← clé suivante I ← charger sous-page de k’
Remarque : Pour que l’accès aux données soit efficace,
b
fils, En pratique, il existe des algos permettant d’assurer que chaque noeud contient entre b/2 et b clés (sauf la racine).
On introduit dans ce chapitre le modèle relationnel qui sert de fondation à la conception de bases de données.
Les différents modèles utiles en représentation des connaissances reposent sur des notions de base de la théorie des ensembles :
Tout commence par une fiche à remplir…
Le Tuple est la structure de données de base servant pour le recueil, le transport et le stockage des données.
t=(a1,...,am) Exemple :
("Dubois", "Martine", 22, "29/10/1994", "Orléans")
<!--
=== Données brutes ===
*Textes,
*comptes rendus,
*série de notes, de valeurs sans format précis :
-> format texte en général.
<note>
Le format ''txt'' désigne des données non structurées de type “texte” regroupant différents modes d’encodage :
* ASCII (caractères sans accent),
* utf8 (caractères accentués et spéciaux),
* ...
</note>
=== Données vectorielles===
* Chaque jeu de valeurs est codé sous la forme d’un **vecteur**
* constitué de grandeurs entières ou réelles :
* toutes les valeurs sont quantitatives (numériques).
* C’est un encodage adapté aux grandeurs physiques :
* chaque champ du formulaire est codé dans un format numérique
* il est possible de représenter les données dans un espace vectoriel
<note important> Un **vecteur** est une séquence (ordonnée et finie) de valeurs quantitatives, chaque valeur obéissant au même format numérique.
</note>
<note tip>
**Exemple** :
Considérons une station météorologique enregistrant à intervalle réguliers les données de ses capteurs :
* thermomètre,
* baromètre,
* hygromètre
* et anémomètre.
Un jeu de valeurs sera constitué de //5 réels double précision// décrivant
* la température,
* la pression,
* l’humidité,
* la vitesse
* et la direction du vent.
</note>
=== Tuples===
**NB**:
* Les données sont organisées sous la forme d’une liste de valeurs qualitatives ou quantitatives.
* Le tuple est la structure de base servant pour la transmission des données (simple, facile à coder et à échanger).
-->
NB: un tuple est une séquence (ordonnée et finie) de valeurs, chaque valeur pouvant être de type qualitatif ou quantitatif, et pouvant obéir à un format numérique différent.
Chaque enregistrement est codé sur une ligne, chaque valeur étant séparé par un caractère séparateur (virgule, point-virgule, tabulation,…).
Exemple :
Dubois,Martine,"28, rue des Lilas, 45000 Orléans",45
Remarques :
Considérons une fiche servant à décrire un étudiant. L’étudiant doit remplir les rubriques nom, prénom et âge, numero de voie, nom de la voie, code postal, ville.
Chaque rubrique correspond à un attribut, où:
La structure de données sous-jacente est le dictionnaire, où l’attribut est la clé permettant d’accéder à la valeur.
Exemple :
{"nom" : "Dubois", "prénom" : "Martine", "adresse" : "28, rue des Lilas, 45000, Orléans", "âge" : 45}
Remarques :
Pour les données organisées de manière hiérarchique. Des balises servent à séparer les différents attributs.
Ex :
<nom> Dubois </nom> <prénom> Martine </prénom> <adresse> <num> 28 </num> <voie> rue des Lilas </voie> <code postal> 45000 </code postal> <ville> Orléans </ville> </adresse> <âge> 45 </âge>
remarque : le format json
permet également de définir des hiérarchies
{ "nom" : "Dubois", "prénom" : "Martine", "adresse" : { "numero" : 28, "voie" : "rue des Lilas", "code_postal" : 45000, "ville" : "Orléans" }, "âge" : 45 }
Un tableau de données est une liste (finie et ordonnée) de tuples, chaque tuple obéissant à un même schéma R.
2 approches en modélisation :
Un tableau de données est une liste (finie et ordonnée) de tuples, chaque tuple obéissant à un même schéma R.
Rappel:
Soit R=(A1,...,Am) un schéma de données
Une relation r obéissant au schéma R est un sous-ensemble du produit cartésien dom(A1)×...×dom(Am)
UML :
Client(nom, prénom, adresse, âge)
Étudiant(nom, prénom, adresse, INE)
Ouvrage(titre, auteur, éditeur, prix, date_édition)
Véhicule(immatriculation, marque, modèle, couleur)
Soit la relation r:
A | B | C |
---|---|---|
1 | a | e |
2 | b | f |
2 | c | f |
3 | d | k |
4 | d | k |
F={num_client, date→num_article, quantité, prixnum_article, quantité→prix}
La contrainte signifie :
Exprimer la dépendance fonctionnelle :
Soit le schéma relationnel suivant :
Billet(num_train, type_train, num_voiture, num_place, date, id_passager, nom_passager, prénom_passager, date_naissance, gare_départ , horaire_départ, gare_arrivée, horaire_arrivée, classe, tarif)
Définir des dépendances fonctionnelles sur cet ensemble d'attributs
Représentation UML :
Soit K une clé candidate. On démontre que K→R à l'aide des axiomes d'Amstrong à partir d'un ensemble de DF connues:
Soit le schéma relationnel suivant :
Billet(num_train, type_train, num_voiture, num_place, date, id_passager, nom_passager, prénom_passager, date_naissance, gare_départ , horaire_départ, gare_arrivée, horaire_arrivée, classe, tarif)
Montrer que l'ensemble {num_train, num_voiture, num_place, date, gare_départ} est une clé primaire du schéma?
Tables mal construites
Fournisseur(nom_f, composant_,adresse_f, prix)
–> Impossible de retrouver les prix pratiqués par les différents fournisseurs.
–> Il est possible de reconstruire la table initiale en effectuant une jointure entre ces 2 tables sur l’attribut nom_f
.
Les Formes normales
R(A1,...,Ai,...,An_,B1,...,Bj,...,Bm)
AiDFE→Bj A1,...,Ai,...,AnDFE→B1,...,Bj−1,Bj+1...,Bm
R1(A1,...,Ai,...,An_,B1,...,Bj−1,Bj+1...,Bm) R2(Ai_,Bj)
Même si aucun attribut ne dépend plus de la clé primaire initiale, il est important de la conserver dans une table spécifique (elle sert à “lier” les valeurs dispersées dans les différentes tables).
Fournisseur(nom_f,composant_,adresse_f, prix) nom_f→adresse_f nom_f, composant→prix
Catalogue(nom_f,composant_,prix) Fournisseur(nom_f_,adresse_f)
La dépendance fonctionnelle entre 2 attributs Ai et Aj est directe s’il n’existe pas de Ak tel que : Ai→Ak→Aj
Un schéma est 3FN :
Commande(num_commande_,nom_f, adresse_f, composant, quantité) num_commande→nom_f, composant, quantité nom_f→adresse_f
Le schéma n’est pas 3FN!! (dépendance transitive entre num_commande et adresse)
* Lorsqu’un schéma relationnel n’est pas en troisième forme normale, il doit être normalisé:
Soit : R(A1,...,Am_,B1,...,Bi,...,Bj,...,Bn) avec : A1,...,AmDFD→B1,...,Bi,...,Bj−1,Bj+1,...,Bn BiDFD→Bj Alors : R1(A1,...,Am_,B1,...,Bi,...,Bj−1,Bj+1,...,Bn) R2(Bi_,Bj)
Comme précédemment, il est important de conserver la clé primaire de la table initiale si elle permet d'associer les valeurs dispersées dans les tables.
Avant :
Après :
L’attribut nom_f est maintenant clé primaire de la table Client et clé étrangère de la table Commande.
Une base de donnée est constituée de plusieurs ensembles d'objets et d'opérateurs participant au bon fonctionnement d'un système:
Exemple 1 :
Exemple 2 :
On parle plus généralement d'ensembles d'entités.
Le modèle entité/associations est une méthode de description des relations entre ensembles d’entités. Il s’appuie sur le prédicat selon lequel tous les éléments des ensembles d’entités sont discernables.
Le modèle entités/associations repose sur un langage graphique de description des données, indépendant du support et de la mise en œuvre informatique.
Une entité x
Les informations conservées au sujet des entités d'un ensemble sont les attributs.
Aj:E→Dj x↦Aj(x)
Un ensemble d'entités est un ensemble fini d'éléments : E={x1,…,xn} Il regroupe (ou associe) plusieurs entités ayant des caractéristiques communes (descriptibles à l'aide du même ensemble d'attributs).
R:X→D1×...×Dm xi↦(A1(xi),…,Am(xi))
Modéliser une base de données, c'est :
Définition : Une association entre les ensembles E1, …, Ek est un sous-ensemble du produit E1×...×Ek.
Il s'agit donc d'un ensemble de k-uplets {...,(x1,…,xk),…} t.q. x1∈E1,…,xk∈Ek.
où k est le degré de l'association :
On donne en général un intervalle [binf,bsup] qui définit le nombre d'apparitions autorisées pour chaque rôle de l'association
Associations de 1 à plusieurs (fonctionnelle)
Relation non symétrique entre les deux ensembles : […,1] d'un côté, […,N] de l'autre. Relation de type contenant/contenu, propriétaire/objet possédé, occupant/occupé, actif/passif etc… Il s'agit du type d'association le plus "courant".
“à gauche” → “à droite”
Associations de plusieurs à plusieurs (croisée)
Dans une association “croisée”, les tous les lien de l’association sont de cardinalité multiple […,N]
A:E→dom(A)
B:E×F→dom(B)
Mesures
Ensembles discernables / non discernables
Opérateurs
Il est possible de traduire un modèle entité/association vers un modèle relationnel (en perdant quelques propriétés).
Un petit nombre de règles permettent de traduire un modèle entité/association vers un modèle relationnel.
Exemple
Une association croisée ne contient que des contraintes de cardinalité de type [..,N]. Soit R une telle association et E1, …, Ek les ensembles participant à l'association.
Soit une association fonctionnelle R. On suppose qu'il existe au moins un ensemble A de cardinalité unique [1,1] participant l’association.
Clients :
nom_client | adresse_client | solde |
---|---|---|
Durand | 7, rue des Lilas | 335,00 |
Dubois | 44, av. du Maréchal Louis | 744,00 |
Duval | 5, place du marché | 33,00 |
Commandes :
num_Commande | nom client | composant | quantité |
---|---|---|---|
6674 | Dubois | micro controller | 55 |
6637 | Dubois | radio tuner | 2 |
6524 | Durand | transistor | 4 |
6443 | Duval | micro controller | 7 |
Fournisseurs :
nom_fournisseur | adresse_fournisseur |
---|---|
Sage | 33, College street, London |
MoxCom | 77 Ashley square,Mumbay |
Catalogue :
nom_fournisseur | composant | prix |
---|---|---|
Sage | transistor | 4,4 |
MoxCom | micro controller | 3,7 |
MoxCom | radio tuner | 7,0 |
Un SGBD (Système de Gestion de Bases de Données) est un programme qui gère une (ou des) base(s) de données. Il s’agit d’un programme optimisé afin d’accélérer l’accès et rationaliser le traitement d’un grand ensemble d’enregistrements stockés sur un support informatique.
Le fonctionnement d'un tel programme repose sur :
Il existe enfin un administrateur de bases de données. Celui-ci doit :
SQL :
CREATE TABLE Commande ( num_commande INTEGER NOT NULL, nom_client VARCHAR(30), nom_fournisseur VARCHAR(30), composant VARCHAR(30), quantité INTEGER, montant DECIMAL(12,2) NOT NULL, PRIMARY KEY (num_commande), FOREIGN KEY (nom_client) REFERENCES Client, FOREIGN KEY (nom_fournisseur, composant) REFERENCES Catalogue);
INSERT INTO Client VALUES ("Durand", "7, rue des Lilas" , 335.00);
UPDATE Client SET adresse = "9, rue des Lilas" WHERE nom_client="Durand";
DELETE FROM Client WHERE nom_client="Durand";
Voir : sql.pdf
Interroger une base de données , c’est sélectionner certaines données parmi l'ensemble des données proposés.
En informatique, une requête (en anglais query) est une demande de consultation ou d'édition, effectuée par un programme client à l’attention d’un programme serveur.
La requête peut être une simple référence vers un fichier, ou être l’expression d’une recherche plus spécifique (consultation de certaines fiches d’un fichier, croisement d’information (entre plusieurs fichiers), etc…). Dans ce cas, il est nécessaire d’utiliser un langage de requête (le plus souvent SQL).
On distingue quatre grands types de requêtes (approche “CRUD”):
Lors d’une consultation de type lecture/recherche, il y a souvent plusieurs réponses qui correspondent à la demande. Le résultat d’une requête prend donc la forme d’un ensemble de réponses. Ces réponses sont éventuellement classées, selon la valeur d’un certain identifiant, ou selon le degré de pertinence.
SELECT * FROM Eleves WHERE NOM = 'Dugenou'
Exemples :
Extraction d'information à partir d'une table unique :
La projection πS(r) est une nouvelle relation de schéma S obtenue à partir des éléments de r restreints au schéma S πS(r)={t(S)|t∈r}
(avec t(S) la restriction de t au schéma S)
nom_fournisseur | adresse_fournisseur | composant | prix |
---|---|---|---|
Sage | 33, College street, London | transistor | 4,4 |
MoxCom | 77 Ashley square,Mumbay | micro controller | 3,7 |
MoxCom | 77 Ashley square,Mumbay | radio tuner | 7,0 |
Requete : Donner la liste des fournisseurs (avec leur adresse): u=πnom_fournisseur, adresse_fournisseur(Catalogue)
→ u :
nom_fournisseur | adresse_fournisseur |
---|---|
Sage | 33, College street, London |
MoxCom | 77 Ashley square,Mumbay |
La sélection σ_F(r) est une nouvelle relation de schéma R , constituée de l'ensemble des enregistrements de r qui satisfont la condition F.
σ_F(r) = \{ t ∈ r | F( t ) \text{est vrai} \}
Requête : Donner la liste des fournisseurs qui vendent des micro-controleurs
u = Π_\text{nom_fournisseur}( σ_\text{Composant = micro controller} ( \text{Fournisseur} )) u :
nom_f |
---|
Moxcom |
Pays :
nom_pays | superficie | population | PIB/hab |
---|---|---|---|
Algérie | 2.300.000 | 31.300.000 | 1630$ |
Niger | 1.200.000 | 11.400.000 | 890$ |
Arabie Saoudite | 2.150.000 | 24.300.000 | 8110$ |
Requête : Donner la liste des pays dont le PIB/hab est > 1000$ u = Π_\text{nom_pays}( σ_\text{PIB/hab > 1000 } ( \text{Pays} ))
u :
nom_pays |
---|
Algérie |
Arabie Saoudite |
SELECT A1,A2, …, An // liste d’attributs FROM R // nom de la TABLE WHERE F // condition sur les attributs
cette requête est semblable à :
soit : Π_{A1, …, An}( σ_F ( R ))
Exemples :
SELECT nom_fournisseur FROM Fournisseur WHERE composant = ’transistor’;
SELECT * FROM Commandes WHERE composant = ’transistor’
SELECT nom_fournisseur FROM Catalogue WHERE composant = ’micro controller’ AND prix < 5
Algo de sélection :
pour tout tuple e de r: si e obéit à la condition F: ajouter e à la réponse
complexité : O(n)
Remarque : dans le cas d'une recherche ciblée, la présence d'un index sur le critère de recherche permet d'accélérer la sélection :
pour toute a ∈ F: i ← Index(a) ajouter r[i] à la réponse
Principe : recoupement d'informations présentes dans plusieurs tables :
On note t ⋃ q le tuple formé des valeurs de t et de q étendues au schéma R ⋃ S
Le produit cartésien r × s est une nouvelle table de schéma R ⋃ S combinant les tuples de r et de s de toutes les façons possibles : r × s = \{t \cup q : t \in r, q \in s\}
r ⋈ s = \{t \cup q : t∈ r, q∈ s, t(R \cap S) = q(R \cap S)\}
Matière_première :
nom_matière | unité | prix |
---|---|---|
pétrole | baril | 45$ |
gaz | GJ | 3$ |
uranium | lb | 12$ |
Exportations :
nom_pays | nom_matière | quantité |
---|---|---|
Algérie | pétrole | 180.000 |
Algérie | gaz | 20.000 |
Niger | uranium | 30.000 |
Arabie Saoudite | pétrole | 2.000.000 |
Arabie Saoudite | gaz | 750.000 |
Matière_première ⋈ Exportations :
nom_pays | nom_matière | quantité | unité | prix |
---|---|---|---|---|
Algérie | pétrole | 180.000 | baril | 45$ |
Algérie | gaz | 20.000 | GJ | 3$ |
Niger | uranium | 30.000 | lb | 12$ |
Arabie Saoudite | pétrole | 2.000.000 | baril | 45$ |
Arabie Saoudite | gaz | 750.000 | GJ | 3$ |
Exemples de requêtes
Π_\text{PIB/hab}( σ_\text{nom_matière = pétrole} ( \text{Pays} ⋈ \text{Exportations} ))
Π_\text{nom_client,adresse_client}( σ_\text{composant = 'micro-controller'} ( \text{Client} ⋈ \text{Commandes} ))
SELECT A1,A2, …, An // liste d’attributs FROM R1, …, Rm // liste de TABLES WHERE F1 AND … AND Fl // liste de conditions sur les attributs // (en particulier conditions sur les attributs // sur lesquel s’effectue la jointure)
Pour exprimer la jointure sur l’attribut 'Aj' commun aux tables 'R1' et 'R2', on écrira : 'R1.Aj = R2.Aj'
Exemples :
SELECT PIB_par_hab FROM Pays NATURAL JOIN Exportations WHERE nom_matiere = 'petrole'
SELECT PIB_par_hab FROM Pays, Exportations WHERE nom_matiere = 'petrole' AND Pays.nom_pays = Exportations.nom_pays
SELECT PIB_par_hab FROM Pays WHERE nom_pays IN ( SELECT nom_pays FROM Exportations WHERE nom_matiere = 'petrole' )
Lors d’une opération de jointure, on distingue en général la “table de gauche” de la “table de droite”.
Il y a deux stratégies possibles pour faire une jointure :
Exemple :
On considère les schémas R(a1,a2,a3) et S(a3,a4,a5) ayant l’attribut a3 en commun :
Soient r et s deux tables obéissant aux schémas R et S, et de taille |r| et |s|.
Algo naif :
Pour chaque tuple e de r: Pour chaque tuple f de s: Si e(a3)=f(a3): ajouter e U f à la réponse
Complexité : O (|r| ×|s|)
Si la table de droite est indexée sur l'attribut a3 qui sert pour la jointure, l’algo suivant peut donner de bons résultats :
Pour chaque tuple e de r: # table de gauche x ← e(a3) i ← Index(x) # index sur la table de droite f ← s[i] ajouter e U f à la réponse
La division r ÷ s est la relation (table) u de schéma R-S maximale contenant des tuples tels que u × s ⊆ r (avec × représentant le produit cartésien)
r ÷ s = \{ t | ∀ q ∈ s, t \cup q ∈ r\}
→ on cherche les éléments de t qui “correspondent” à s
Exemples :
L'union r1 U r2 est une nouvelle table de schéma R constituée de l'ensemble des enregistrements qui appartiennent à r1 ou à r2: r1 \cup r2 = { t ∈ r1} \cup { t ∈ r2}
L'intersection r1 ⋂ r2 est une nouvelle table de schéma R constituée de l'ensemble des enregistrements qui appartiennent à r1 et à r2: r1 \cap r2 = \{ t ∈ r1\} \cap \{ t ∈ r2\}
La différence r1 - r2 est une nouvelle table de schéma R constituée de l'ensemble des enregistrements qui appartiennent à r1 mais pas à r2: r1 - r2 = \{ t ∈ r1\} - \{ t ∈ r2\}
Exemples :
\pi _{Pays} σ_\text{matière = gaz} (\text{Exportations}) \cap \pi _{Pays} σ_\text{matière = pétrole} (\text{Exportations}) en SQL :
SELECT pays FROM Exportations WHERE matière = 'gaz' INTERSECT ( SELECT pays FROM EXPORTATIONS WHERE matière = 'pétrole');
\pi _{Pays} σ_\text{matière = gaz} (\text{Exportations}) - \pi _{Pays} σ_\text{matière = pétrole} (\text{Exportations}) en SQL :
SELECT pays FROM Exportations WHERE matière = 'gaz' EXCEPT ( SELECT pays FROM EXPORTATIONS WHERE matière = 'pétrole');
* Donner la liste des clients qui commandent uniquement des produits 'Moxcom' : \pi_{nom\_client}Client - \pi_{nom\_client} \sigma_{fournisseur \neq 'Moxcom'} Client ⋈ Commande en SQL :
SELECT nom_client FROM Client EXCEPT ( SELECT client FROM Client NATURAL JOIN Commande WHERE fournisseur <> 'Moxcom');
L’analyse des données a pour but de recomposer l’information contenue dans les données recueillies afin d’en fournir une vue plus synthétique, ou d’extraire des informations qui n’apparaissent pas de façon explicite dans la série de mesures initiale :
Exemples de grandes masses de données :
Le but est de dégager :
à partir d’un grand ensemble de données (chiffre d’affaires, nb de ventes, masse salariale, …) évoluant dans le temps et dans l’espace, afin de
L'agrégation consiste:
count
, sum
, mean
, avg
, max
, min
…)cas d’utilisation :
En SQL, l'opérateur d'agrégation est GROUP BY
:
Exemples de requêtes faisant appel aux fonctions d’agrégation :
Nombre d’élèves par groupe de TD / par prépa d’origine etc..:
SELECT groupe_TD , COUNT(num_eleve) FROM Eleve GROUP BY groupe_TD
Donner les chiffres des ventes du magasin pour chaque mois de l’année
SELECT mois, SUM(montant) FROM Vente GROUP BY mois
Donner le nombre de ventes d’un montant > à 1000 euros pour les mois dont le chiffre d'affaires est supérieur à 10000 euros
SELECT mois, COUNT(num_vente) FROM Vente GROUP BY mois HAVING SUM(montant) >= 10000
Tester les disparités salariales entre hommes et femmes
SELECT sexe, avg( salaire ) FROM Employé GROUP BY sexe
Tester les disparités salariales selon le niveau d’éducation
SELECT niveau_educatif, avg( salaire ) FROM Employé GROUP BY niveau_éducatif
La découverte d'informations consiste à développer des outils de mise en forme des données facilitant leur analyse. Elle repose sur deux aspects :
Le but est ici de dégager :
Exemples de corrélations :
Sites de données :
Remarque : Les transactions marchandes sont un cas classique (acte d’achat bien répertorié et enregistrés, livres de comptes, …)
Exemples de “fait”:
Tous ces faits peuvent être localisés. Des mesures peuvent être effectuées sur ces faits (montant d’une vente, durée d’un appel, montant d’une opération bancaire, …)
Points clés :
Les tables pivot permettent d'analyser des faits selon deux dimensions organisées sur les deux axes d'un tableau.
L'utilisation de données structurées dans un programme Python nécessite de faire appel à des librairies spécialisées. Nous regardons ici la librairie pandas
qui sert à la mise en forme et à l'analyse des données.
import numpy as np import matplotlib.pyplot as plt import pandas
Considérons des informations stockées dans un fichier au format ‘csv’ (comma separated values) : ventes_new.csv
On utilise:
pandas.read_csv
. Voir dataframes pandas. Pandas permet également de lire les données au format xls
et xlsx
(Excel). with open('ventes_new.csv') as f: data = pandas.read_csv(f) print(data)
avec data
une structure de données de type DataFrame
.
exemple : on représente les ventes selon (1) la dimension géographique et (2) la dimension temporelle
T = pandas.pivot_table(data, values = 'MONTANT', index = ['PAYS'], columns = ['ANNEE'], aggfunc=np.sum) print(T)
Evolution des ventes au cours de l'année pour la France seulement:
selection = data[data.PAYS == "France"] T2 = pandas.pivot_table(selection, values = 'MONTANT', index = ['ANNEE'], columns = ['VILLE'], aggfunc=np.sum) print(T2) T2.plot(kind='bar', subplots = 'True') plt.show()
Ici les données sont organisées autour de plusieurs dimensions. L'agrégation consiste:
Exemple de hiérarchie:
Problèmes :
etc…
Un cube de données est une structure de données organisée sur le principe des espaces vectoriels. Différents axes sont définis, chaque axe étant associé à une dimension particulière.
Un élément essentiel du modèle de données est la définition de hiérarchies sur les dimensions du cube. Chaque dimension se divise en intervalles et sous-intervalles (pour le continu/ quantitatif) ou en catégories et sous-catégories (pour le discret/qualitatif)
Les hiérarchies sur les différentes dimensions permettent de définir le “niveau de résolution” sur les différentes dimensions.
La structure de cube de données est adaptée pour la réalisation d’histogramme multidimensionnels, selon les axes choisis et le niveau de résolution choisi, à l’aide de fonctions d’aggrégation.
REPRESENTATION DES DONNEES : Représenter des jeux de valeurs de grande taille de façon plus synthétique (algorithmes de réduction de dimension)
REGROUPEMENT (“CLUSTERING”) : Définir des regroupements (ou des classements simples ou hiérarchiques) entre jeux de valeurs
COMPLETION : Méthodes de classification automatique (ou d’interpolation) visant à deviner soit la classe, soit certaines valeurs non mesurées, à partir d’un jeu de valeurs et d’une base d’exemples complets. Il existe des méthodes paramétriques ou non paramétriques.
ESTIMATION ET DECISION : Méthodes visant à estimer la “valeur” associée à un jeu de données (pour l’aide à la décision)