Les données R

De EduTech Wiki
Aller à la navigation Aller à la recherche
La version imprimable n’est plus prise en charge et peut comporter des erreurs de génération. Veuillez mettre à jour les signets de votre navigateur et utiliser à la place la fonction d’impression par défaut de celui-ci.
Analytique et exploration de données
Module: Tutoriels R
◀▬▬▶
brouillon intermédiaire
2022/04/15 ⚒⚒ 2014/11/18
Prérequis
Voir aussi
Catégorie: R

Introduction aux données R

Pour profiter pleinement de divers paquets il faut comprendre (a) les types de structures de données de R et (b) les structures de données implémentés par divers paquets et (c) comment passer d'une structure à l'autre et finalement (d) comment lire des données depuis des fichiers ou d'autres sources.

Plusieurs paquets utilisent des simples structures de données de base comme les vecteurs ou les matrices. D'autres utilisent des structures plus sophistiqués

Cet article essaye de présenter de façon systématique les différents types de données, y compris le système des "classes".

A notre avis, il n'est pas nécessaire de lire ou comprendre tout en détail, mais le lecteur peut revenir plus tard. Contrairement à d'autres logiciels d'analyse de données R n'utilise pas une seule structure centrale, mais une multitude de représentations. Cela rend R plus flexible, mais plus difficile à aborder au début.

Les types de données

Il existe 3 grandes classes de données:

  • Vecteurs simples: Ce sont des simples listes ordonnées de valeurs simples
  • Données composites (listes, data frames, etc.)
  • Données "spéciales" pour programmeurs

Il existe 6 types de valeurs simples: "logical", "integer", "double", "complex", "character", "raw"

Comment savoir le type d'une donnée ?
Utilisez la fonction typeof
typeof (truc)
nom <- "DKS"
typeof (nom)
[1] "character"

Lorsqu'on utilise cette fonction avec un vecteur (voir ci-dessous pour une explication de ce terme), le résultat ne montre pas "vector", mais le type de données utilisées, tout simplement parce que l'objet le plus simple est un vecteur. Les deux expressions suivante sont équivalentes:

v1 = "Simple"
v2 = c ("Simple") # on construit explicitement un vecteur

D'où la décision des gens de R de ne pas afficher "vector", mais simplement le type de données qui se trouvent dans le vecteur.

> typeof ( c("DKS", "TECFA"))
[1] "character"

Il existe plusieurs types de structures de données, dont nous présentons certains.

Type Définition Exemples Utilisation
vector Liste indexée du même type de données Ex: "ceci" "est" "une"
Ex: 1 2 3
Ex: "ceci"
Structure de base pour représenter des données, par exemple une seule valeur ou encore une variable statistique avec 10'137 entrées. Voir les data frame qui sont composés de vecteurs.
matrix Tableau typé à 2 dimensions Exemple:
1 2 3
4 5 6
17 18 19
On peut penser une matrice comme un vecteur à 2 dimensions. Les utilisateurs de R semblent utiliser plus souvent des data frame pour représenter des données, car on peut (1) annoter les colonnes et (2) avoir des types de vecteurs différents.
factor Vecteur pour variables nominales mot image mot image mot
Levels: image mot
Utile pour stocker et analyser des valeurs nominales (mots au lieu de chiffres)
array ... ... ...
list Une liste de données qui peut contenir d'autres structures de données complexes Ex:"un" "mot" "dit" Structure la plus flexible. On peut tout représenter avec une liste de listes de listes ...
list (associative) même type que la liste Ex:art="un", sujet="mot", verbe="dit" Permet d'indexer / chercher / tagger des données
data frame Tableau composé de type de données différentes.
phrase_courte phrase_courte2 phrase_courte3
art             un            une            une
sujet           mot          image           idee
verbe           dit          parle            est
On peut penser à une liste de vecteurs ou de facteurs ou un tableau de type Excel.

Note: Etant donné que R possède une sémantique inspiré de langages puissants comme Scheme, tout est données, y compris les fonctions.

Les classes

Pour chaque type, R définit aussi une classe. Un type représente l'organisation des données et la classe ce qu'on peut faire avec.

Pour identifier le type de structure de données, il faut plutôt utiliser class à la place de typeof, car la classe nous renseigne sur les méthodes que l'on peut utiliser pour manipuler un objet. Enfin le résultat n'est pas toujours intuitif. Par défaut tout est un vecteur et donc R au lieu de dire "ceci un caracter vector" dit simplement "character"....

noms_11 <- ( c("DKS", "TECFA"))
> class (noms_11)
[1] "character"
> is.vector(noms_11)
[1] TRUE

L'exemple suivant montre la différence entre structure de données (un data frame est effectivement une liste d'un point de vue structurel) et une classe:

# df_mots est un data frame
> typeof (df_mots3)
[1] "list"
> class (df_mots3)
[1] "data.frame"

Voir aussi les explications plus loin qui montrent que R possède plusieurs types de classes et correspondent à l'évolution du langage dans le temps...

Les vecteurs

Contiennent une liste ordonnée de N éléments.
Ce type de structure de données est fréquent. On l'utilise pour représenter des données d'une variable statistique, par exemple une liste de revenues ou encore une liste de noms.
Voir les matrice (ci-dessous pour des vecteurs à N dimensions que l'on peut utiliser pour représenter des tableaux de données par exemple)
Construction manuelle d'une liste
Il existe plusieurs méthodes. Le plus souvent on voit la fonction combine: c()
proverbe = c("un", "mot", "dit", "plus", "que", "une", "image");

Altérnativement, vous pouvez utiliser l'opérateur : , la fonction seq et la fonction rep :

 1:15
 seq(1,5, by = 0.2)
 seq(1,5, length=10)
 rep(1,10)
 rep(1:3, times = 3)
 rep(1:3, each = 3)
 rep(1:3, times = 3, each = 2)

La fonction rep() permet de générer un vecteur avec des éléments identiques

>rep('H', 20)
 [1] "H" "H" "H" "H" "H" "H" "H" "H" "H" "H" "H" "H" "H" "H" "H" "H" "H" "H"
[19] "H" "H"

La fonction seq permet de générer des vecteurs avec des éléments calculés

 1:15
 seq(1,5, by = 0.2)
 seq(1,5, length=10)
 rep(1,10)
 rep(1:3, times = 3)
 rep(1:3, each = 3)
 rep(1:3, times = 3, each = 2)

Pour générer un vecteur logique, utilisez les opérateurs >, >=, <, <=, ==, != :

10 == (2+1) # Donne FALSE car 10 est différent de 3
10 != 3 # Donne TRUE car 10 est différent de 3
10 >= 7 # Donne TRUE car 10 est supérieur égal à 7
1:10 == 6 # Donne un vecteur logique de longueur 10. La valeur TRUE apparaît quand la condition est satisfaite ; la valeur FALSE apparaît quand la condition n'est pas satisfaite

Rappelons que les opérateurs <- et -> permettent de sauvegarder des objets dans la mémoire de R. Créons un vecteur numérique Age et un vecteur alphanumérique Sexe à travers les commandes suivantes :

Age <- c(19, 31, 28, 18, 25, 23, 27, 20)
Sexe <- c('F', 'H', 'F', 'H', 'H', 'F', 'H', 'F')

Affichons enfin les deux vecteurs avec les commandes :

Age
Sexe
Sélection d'éléments

Pour sélectionner une partie d'un vecteur, utilisez l'opérateur de sélection [ ]. Etudiez les exemples suivants :

X = 10:20 # crée un vecteur qui contient une série qui va de 10 à 20
X[3] # Donne le troisième élément du vecteur X
X[c(6,9)] # Donne le sixième et neuvième élément du vecteur X
X[3:5] # Donne le troisième quatrième et cinquième élément du vecteur X
X[7:5] # Donne le septième, le sixième et le cinquième élément du vecteur X
X[-c(4,7)] # Donne X sans le quatrième et septième élément du vecteur X
X[-(1:3)] # Donne X sans les trois premiers éléments
X[(X<15)] # Donne les éléments de X inférieur à 15
X[(X<17) & (X>13)] # Donne les éléments de X inférieurs à 17 ET supérieurs à 13
X[(X<13) | (X>17)] # Donne les éléments de X inférieurs à 13 OU supérieurs à 17
Exemple complet
proverbe = c("un", "mot", "dit", "plus", "que", "une", "image");

> proverbe[1]
[1] "un"
> proverbe[2:3]
[1] "mot" "dit"

Les facteurs

Il s'agit d'une sorte de vecteur qui stocke de façon un peu plus efficace des chaînes de caractères. C'est surtout utile lorsqu'on a des longues listes de valeurs nominales.
Construction
On utilise la fonction factor pour transformer un vecteur en facteur
> proverbe2 = c ("mot", "image", "mot", "image", "mot")
> facts = factor(proverbe2)
> facts
[1] mot   image mot   image mot  
Levels: image mot
> proverbe2
[1] "mot"   "image" "mot"   "image" "mot"


Les listes

Une liste est comme un vecteur, mais peut contenir des données de type différent, y compris des listes. La représentation d'une liste est un peu plus verbeuse.

Une liste simple se construit comme un vecteur, enfin on utilise la fonction list
// Un vecteur
>emotions = c ("n", "chaud", "n", "chaud", "n", "froid")
>valeurs  = c (0,2,0,1,0,-2)

// Une liste
> emotions2 = list ("n", "chaud", "n", "chaud", "n", "froid")
> emotions
[[1]]
[1] "n"

[[2]]
[1] "chaud"

[[3]]
[1] "n"

[[4]]
[1] "chaud"

[[5]]
[1] "n"

[[6]]
[1] "froid"

Une liste qui contient des listes peut se construire à partir de listes ou de vecteurs. Les listes imbriquées ne doivent pas forcément avoir la même longueur.

Liste qui contient des vecteurs
> liste_10 = list (proverbe, emotions, valeurs)
> liste_10
[[1]]
[1] "un"    "mot"   "dit"   "plus"  "que"   "une"   "image"

[[2]]
[1] "n"     "chaud" "n"     "chaud" "n"     "froid"

[[3]]
[1]  0  2  0  1  0 -2
Exemple qui contient une liste

emotions2 = list ("n", "chaud", "n", "chaud", "n", "froid")

> liste_11 = list (proverbe2, emotions, valeurs)
> liste_11
[[1]]
[1] "mot"   "image" "mot"   "image" "mot"   "image"

[[2]]
[[2]][[1]]
[1] "n"

[[2]][[2]]
[1] "chaud"

[[2]][[3]]
[1] "n"

[[2]][[4]]
[1] "chaud"

[[2]][[5]]
[1] "n"

[[2]][[6]]
[1] "froid"


[[3]]
[1]  0  2  0  1  0 -2

> liste_11[2]
[[1]]
[[1]][[1]]
[1] "n"

[[1]][[2]]
[1] "chaud"

[[1]][[3]]
[1] "n"

[[1]][[4]]
[1] "chaud"

[[1]][[5]]
[1] "n"

[[1]][[6]]
[1] "froid"
Afficher un élément de liste
// Lister le 2ème élément (une liste dans notre cas)
> liste_10[2]
[[1]]
[1] "n"     "chaud" "n"     "chaud" "n"     "froid"

Les listes associatives

On peut donner un nom aux éléments de liste. Cela permet par exemple de faire des simples base de données ou encore de "tagger" les mots d'un texte avec des annotations.

Construction d'une liste associative
On utilise la même fonction list, mais entre chaque valeur comme une paire clef=valeur
> phrase_courte = list (art="un", sujet="mot", verbe="dit")
> phrase_courte
$art
[1] "un"

$sujet
[1] "mot"

$verbe
[1] "dit"

Les matrices

Les matrices sont des tableaux à N dimensions, typiquement un tableau à 2 dimensions. Pensez à une feuille de tableur.
Une matrice contient des éléments du même type, par exemple des nombres ou encore des "strings" (chaîne de caractères) comme dans les exemples ci-dessous. Autrement dit, dans une matrice on ne peut pas retrouve à la fois des nombres et des strings.
Construction manuelle d'une matrice à partir d'une liste
> m <- matrix(c('ah', 'be', 'cé', 'dé', 'euh', 'eff', 'gé', 'asch'), nrow = 2)
> m
     [,1] [,2] [,3]  [,4]  
[1,] "ah" "cé" "euh" "gé"  
[2,] "be" "dé" "eff" "asch"
Construction d'une matrice à partir de vectors
Notez que l'on construit d'abord un long vecteur avec la fonction c
mat <-matrix ( c(phrase_courte, phrase_courte2, phrase_courte3), nrow=3)
mat
Extraire des données
On utilisela notation [ligne,colonne]
> m[1,]
[1] "ah"  "cé"  "euh" "gé" 
> m[,2]
[1] "cé" "dé"
> m[2,1]
[1] "be"

Les array

Les array (tableaux en français) ressemblent à des matrices, mais contiennent des informations supplémentaires

.....

Les data frames

Un data frame est un tableau composé de types de données différentes. On peut conceptualiser cela comme une sorte de combinaison entre une matrice et une liste à N dimensions ou mieux comme une collection de vecteurs la même longueur. Chaque vecteur est représenté comme une colonne et il possède un nom. En gros, on retrouve les tableaux de type Excel, SPSS, etc.

Exemple de construction manuelle d'un data frame à partir de vecteurs représentation une variable.
Par définition, R va identifier des "facteurs" (ou "levels"), c-a-d constituer une liste de différentes valeurs
> articles = c( "un", "le", "la", "les")
> sujets = c( "mot", "terme", "chose", "images")
> df_mots  <- data.frame (articles, sujets)
> df_mots
  articles sujets
1       un    mot
2       le  terme
3       la  chose
4      les images
> typeof(df_mots)
[1] "list"
Sortir des éléments
df_mots[3,1]
[1] la
Levels: la le les un
Notez que R indique des "levels". Il s'agit de catégories (strings différents) que l'on retrouve dans un vecteur
Construire un data frame sans "facteurs"
> df_mots2  <- data.frame (articles, sujets, stringsAsFactors = FALSE)
> df_mots2[3,1]
[1] "la"
Exemple de construction manuelle d'un data frame à partir de données "cas"
On construit d'abord des simples vecteurs à clef et ensuite on les combine
phrase_courte = c (art="un", sujet="mot", verbe="dit")
phrase_courte2 = c (art="une", sujet="image", verbe="parle")
phrase_courte3 = c (art="une", sujet="idee", verbe="est")

phr <- data.frame (phrase_courte, phrase_courte2, phrase_courte3)
phr
      phrase_courte phrase_courte2 phrase_courte3
art              un            une            une
sujet           mot          image           idee
verbe           dit          parle            est

Cette représentation n'est pas vraiment standarde. Normalement on présenterait chaque phrase en ligne. On peut donc permuter le data frame en utilisation la fonction t et en spécifiant que le résultat doit de nouveau être un data frame avec la fonction as.data.frame (sinon cela devient une matrice simple)

> phrases = as.data.frame(t(phr))
> phrases
               art sujet verbe
phrase_courte   un   mot   dit
phrase_courte2 une image parle
phrase_courte3 une  idee   est
Utilisation de "variables" / vecteurs
Chaque colonne représente une variable statistique (à ne pas confondre avec une variable de programmation ou "nom d'objet")
Pour référencer une "colonne" (pensez "variable"), on utilise la notation votre_data_frame$nom_colonne
> phrases$art
 phrase_courte phrase_courte2 phrase_courte3 
            un            une            une 
Levels: un une
> phrases$sujet
 phrase_courte phrase_courte2 phrase_courte3 
           mot          image           idee 
Levels: idee image mot
Attacher / détacher un data frame
Comme le data frame est la structure utilisé pour représenter un jeu de données quantitatif ou qualitatif/quantitatif, R permet permet d'attacher un data frame pour l'analyse.

Exemple d'un data frame:

df_mots3  <- data.frame (art = c( "un", "le", "la", "les"), 
                         adj = c("gros", "petit", "drole de", "belles"), 
                         suj = c( "mot", "terme", "chose", "images"),
                         stringsAsFactors = FALSE)
> df_mots3
  art      adj    suj
1  un     gros    mot
2  le    petit  terme
3  la drole de  chose
4 les   belles images

Extraire une variable (vecteur):

> df_mot3$art
> df_mots$art
[1] un  le  la  les
Levels: la le les un

Attacher un data frame avec attach():

> art
Error: object 'art' not found
> df_mots$art
[1] un  le  la  les
Levels: la le les un
> attach (df_mots3)
> art
[1] "un"  "le"  "la"  "les"

Détachez ensuite data frame avec detach()

detach (df_mots3)

Résumé d'opérations pour accéder aux structures de données

Accéder aux données juste pour voir ce qu'il y a l'intérieur est une des plus grandes frustrations pour le débutant (en cas pour nous). Il existe une panoplie de structures et les messages d'erreur ou les non messages ne renseignent guerre sur ce qu'on a mal fait.

Syntaxe Type d'objets Détails Exemple
x[i] Vecteurs et listes i est un nombre, un string ou un vecteurs des deux. Retourne un vecteur ou une liste d'objets (même pour une seule valeur)
> obj= c(1,2,3,4)
> obj[2]
[1] 2
> obj[2:3]
[1] 2 3
x[[i]] Vecteurs et listes Retourne un élément singulier
 > obj[[2]]
[1] 2
> obj[[2:3]]
Error in obj[[2:3]] : attempt to select more than one element
x$nom
x["nom"]
Listes Retourne un objet nommé "nom"
ma_s3 = list (fleur = "Une jolie fleur rouge", arbre = "Un tronc brun et des feuilles vertes")
> ma_s3$fleur
[1] "Une jolie fleur rouge"
> ma_s3["fleur"]
$fleur
[1] "Une jolie fleur rouge"
x@nom Objets S4 Retourne un objet nommé "nom"
x[[i]][j]
liste à vecteurs Les combinaisons sont difficiles à comprendre. Si on a une liste avec des vecteurs nommées il faut extraire un élément simple de la liste et ensuite l'élément du vecteur
 ma_liste_vect = list (fleur = c ("Une", "jolie", "fleur", "rouge"), arbre = c ("Un", "tronc", "brun", "et", "des", "feuilles", "vertes"))
> ma_liste_vect[1]
$fleur
[1] "Une"   "jolie" "fleur" "rouge"
> ma_liste_vect[1][2]
$<NA>
NULL
> ma_liste_vect[[1]][2]
[1] "jolie"
> ma_liste_vect[[1]][[2]]
[1] "jolie"

Et encore ....

ma_liste_vect = list (fleur = c ("Une", "jolie", "fleur", "rouge"),
                      arbre = c ("Un", "tronc", "brun", "et", "des", "feuilles", "vertes"))

for (j in seq.int (ma_liste_vect)) {
  print (paste ("j=", j, ", Length=", length (ma_liste_vect[[j]])))
}

Les classes

R possède trois différents types de classes et probablement autant d'extensions.

Classes et objets S3

Les objets S3 représentent la "old school object-oriented programming" dans R. A éviter pour tout projet nouveau, mais il faut savoir les utiliser, car beaucoup de paquet utilisent encore cette infrastructure. Les classes S3 implémentent la possibilité de définir des fonctions du même nom qui agissent différemment en fonction du type de input. Les propriétés d'une classe sont des simples attributs.

La fonction unclass() permet d'inspecter un objet

>unclass(ovid)

content
$content[[1]]
<<PlainTextDocument (metadata: 7)>>
    Si quis in hoc artem populo non novit amandi,
         hoc legat et lecto carmine doctus amet.
    arte citae veloque rates remoque moventur,
    
    [....]

$content[[2]]
<<PlainTextDocument (metadata: 7)>>
    quas Hector sensurus erat, poscente magistro
         verberibus iussas praebuit ille manus.
    [...]
$meta
list()
attr(,"class")
[1] "CorpusMeta"

$dmeta
data frame with 0 columns and 5 rows

La fonction attributes permet de voir les attributs:

> attributes(ovid)

$names
[1] "content" "meta"    "dmeta"  

$class
[1] "VCorpus" "Corpus" 

Examiner un seul document:
<source lang="matlab">
> class(ovid[[1]])
[1] "PlainTextDocument" "TextDocument"

Regarder les colonnes d'un data frame dans une classe S3

> ovid[[1]]$meta
Metadata:
  author       : character(0)
  datetimestamp: 2014-11-25 15:53:09
  description  : character(0)
  heading      : character(0)
  id           : ovid_1.txt
  language     : lat
  origin       : character(0)
# Equivalent à
> meta(ovid[[1]])
Metadata:
  author       : character(0)
  datetimestamp: 2014-11-25 15:53:09
  description  : character(0)
  heading      : character(0)
  id           : ovid_1.txt
  language     : lat
  origin       : character(0)
Créer une classe S3

Tout d'abord on peut déclarer qu'un objet appartient à une classe en ajouter un nom avec la fonction class()

> ma_s3 = list (fleur = c ("Une, jolie, fleur, rouge"), arbre = c( "Un, tronc, brun, et, des, feuilles, vertes"))
> class (ma_s3)
[1] "character"
> class (ma_s3) <- append (class (ma_s3), "PhrasesPlantes")

> class (ma_s3)
[1] "character"      "PhrasesPlantes"

> ma_s3
$fleur
[1] "Une, jolie, fleur, rouge"

$arbre
[1] "Un, tronc, brun, et, des, feuilles, vertes"

attr(,"class")
[1] "list"           "PhrasesPlantes"

Maintenant, on pourrait créer des méthodes pour cette classe inutile.

Classes et objets S4

Les objets S4 sont des structures de données complexes basées sur une une classe, c'est-à-dire une définition abstraite d'une structure de données avec des méthodes associées. Ce type d'objet est produit par certaines analyses, par exemple la fonction treetag() du paquet koRpus. Ce type de classes et de méthodes ont été introduits dans le language S avec la version 4. D'où leur nom étrange S4. Il s'agit tout simplement de la partie "objets moderne" du langage. Il existe aussi une version plus ancienne, S3.

References classes

Les "reference classes" étendent les classes S4 avec une autre syntaxe et un autre modèle pour les objets

  • Les objets utilisent des références. Cela veut dire qu'un changement dans les données est permanent. Un objet S4 retourne juste un résultat changé, mais l'objet reste tel quel.
  • Les méthodes sont stockés dans la classe.

... En gros, ces classes fonctionnent comme des classes C++ ou Java

Autres

Il existe d'autres structures de données que l'on introduit pas pour le moment.

Il est par contre important de savoir que certains paquetages (extensions) implémentent leur propre structure de données en utilisant des classes S3, S4 ou reference. C'est notamment le cas de l'extension text mining tm qui implémente Corpus avec une classe S3.

Conversions

Conversion de types

La fonction as (objet, type) permet de transformer un type de structure de données en une autre si possible.

> deux <- "2"
> deux2 <- as (deux, "numeric")
> deux
[1] "2"
> deux2
[1] 2

Exemple raté:

> trois <- "3 chats"
> trois3 <- as (trois, "numeric")
Warning message:
In asMethod(object) : NAs introduced by coercion
> trois3
[1] NA

Fonctions de conversion spécialisées

Il existe une panoplie de fonctions qui commencent par as. et qui font la coercition si possible. Par exemple

  • as.vector
  • as.vector.factor
  • as.matrix
  • as.array
  • as.list
  • as.data.frame

Ces fonctions sont bien documentées et prennent plusieurs arguments qu'on peut utiliser dans des cas de conversion plus compliqués.

Exemple data frame vers matrice
> df_mots3
  art      adj    suj
1  un     gros    mot
2  le    petit  terme
3  la drole de  chose
4 les   belles images

> mat_mots3 <- as.matrix(df_mots3)
> mat_mots3
     art   adj        suj     
[1,] "un"  "gros"     "mot"   
[2,] "le"  "petit"    "terme" 
[3,] "la"  "drole de" "chose" 
[4,] "les" "belles"   "images"

La fonction as.matrix possède plusieurs arguments qui facilite une conversion dans des situations plus compliqués.

Il faut également veilleur à examiner les fonctions de base pour voir si elle ne font pas conversions. Par exemple, pour passe d'un vecteur simple à une matrice, on utilisera matrix

# On définit une liste
liste_bete <- c (1,2,3,4,5,6)
# On matrixifie
matrix ( liste_bete, nrow =2, ncol=3)
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6


Suject connexes

Gestion de l'encodage

Il est important de bien gérer les encodages. A priori il faut toujour veiller à tout faire en UTF-8. Il arrive malheureusement de

  • tomber sur des textes encodés dans un format archaique (comme ISO-latin ou pire une variante Windows)
  • tomber sur des paquets R qui par défaut utilisent un encodage ascii ou ISO.

(à compléter)