Skip to content

Commit

Permalink
chapitre listes et tableaux de données
Browse files Browse the repository at this point in the history
  • Loading branch information
larmarange committed Jul 17, 2015
1 parent a57a887 commit 4400b6f
Showing 1 changed file with 364 additions and 0 deletions.
364 changes: 364 additions & 0 deletions listes-et-tableaux-de-donnes.Rmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,364 @@
---
title: "Listes et Tableaux de données"
---

```{r options_communes, include=FALSE}
source("options_communes.R")
```

<div class="important">
Ce chapitre est en cours d'écriture.
</div>

<div class="note">
Il est préférable d'avoir déjà lu le chapitre [Vecteurs, indexation et assignation](vecteurs-indexation-et-assignation.html) avant d'aborder celui-ci.
</div>

## Listes

Par nature, les vecteurs ne peuvent contenir que des valeurs de même type (numériques, textuels ou logique). Or, on peut avoir besoin de représenter des objets plus complexes composés d'éléments disparates. C'est ce que permettent les <dfn data-index="liste">listes</dfn>.

### Propriétés et création

Une liste se créée tout simplement avec la fonction `list`{data-pkg="base"} :

```{r}
l1 <- list(1:5, "abc")
l1
```

Une liste est un ensemble d'objets, quels qu'ils soient, chaque élément d'une liste pouvant avoir ses propres dimensions. Dans notre exemple précédent, nous avons créée une liste `l1` composée de deux élements : un vecteur d'entiers de longeur 5 et un vecteur textuel de longueur 1. La longueur d'une liste correspond aux nombres d'éléments qu'elle contient et s'obtient avec `length`{data-pkg="base"} :

```{r}
length(l1)
```

Comme les vecteurs, une liste peut être nommées et les noms des éléments d'une liste accessibles avec `names`{data-pkg="base"} :

```{r}
l2 <- list(minuscules = letters, majuscules = LETTERS, mois = month.name)
l2
length(l2)
names(l2)
```

Que se passe-t-il maintenant si l'on effectue la commande suivante ?

```{r}
l <- list(l1, l2)
```

À votre avis, quelle est la longueur de cette nouvelle liste `l` ? 5 ?

```{r}
length(l)
```

Et bien non ! Elle est de longeur 2, car nous avons créé une liste composée de deux éléments qui sont eux-mêmes des listes. Cela est plus lisible si l'on fait appel à la fonction `str`{data-pkg="utils"} qui permet de visualiser la structure d'un objet.

```{r}
str(l)
```

Une liste peut contenir tout type d'objets, y compris d'autres listes. Pour combiner les éléments d'une liste, il fait utiliser la fonction `append`{data-pkg="base"} :

```{r}
l <- append(l1, l2)
length(l)
str(l)
```

On peut noter en passant qu'une liste peut tout à fait n'être que partiellement nommée.

### Indexation

Les crochets simples (`[]`) fonctionnent comme pour les vecteurs. On peut utiliser à la fois l'<dfn>indexation par position<dfn><dfn data-index="position, indexation"></dfn>, l'<dfn>indexation par nom</dfn><dfn data-index="nom, indexation"></dfn> et l'<dfn>indexation par condition</dfn><dfn data-index="condition, indexation"></dfn>.

```{r}
l
l[c(1,3,4)]
l[c("majuscules", "minuscules")]
l[c(TRUE, TRUE, FALSE, FALSE, TRUE)]
```

Même si l'on extrait un seul élément, l'extraction obtenue avec les crochets simples renvoie toujours une liste, ici composée d'un seul élément :

```{r}
str(l[1])
```

Supposons que je souhaite calculer la moyenne des valeurs du premier élément de ma liste. Essayons la commande suivante :

```{r}
mean(l[1])
```

Nous obtenons un message d'erreur. En effet, **R** ne sait pas calculer une moyenne à partir d'une liste. Ce qu'il lui faut, c'est un vecteur de valeurs numériques. Autrement dit, ce que nous cherchons à obtenir c'est le contenu même du premier élément de notre liste et non une liste à un seul élément.

C'est ici que les doubles crochets (`[[]]`) vont rentrer en jeu. Pour ces derniers, nous pourrons utiliser l'indexation par position ou l'indexation par nom, mais pas l'indexation par condition. De plus, le critère que l'on indiquera doit indiquer un et un seul élément de notre liste. Au lieu de renvoyer une liste à un élément, les doubles crochets vont renvoyer l'élément désigné. Vite, un exemple :

```{r}
str(l[1])
str(l[[1]])
```

Maintenant, nous pouvons calculer notre moyenne :

```{r}
mean(l[[1]])
```

Nous pouvons aussi tester l'indexation par nom,

```{r}
l[["mois"]]
```

mais il faut avouer que cette écriture avec doubles crochets et guillemets est un peu lourde. Heuresement, un nouvel acteur entre en scène : le symbole dollar (`$`). C'est un raccourci des doubles crochets pour l'indexation par nom. Que l'on utilise ainsi :

```{r}
l$mois
```

Les écritures `l$mois` et `l[["mois"]]` sont équivalentes. Attention ! Cela ne fonctionne que pour l'indexation par nom.

```{r, eval=FALSE}
l$1
```
```
Error: unexpected numeric constant in "l$1"
```

L'<dfn>assignation par indexation</dfn><dfn data-index="indexation, assignation"></dfn> fonctionne également avec les doubles crochets ou le signe dollar :

```{r}
l[[2]] <- list(c("un", "vecteur", "textuel"))
l$mois <- c("Janvier", "Février", "Mars")
l
```

## Tableaux de données

Il y a un type d'objets que nous avons déjà abordé dans le chapitre [Premier travail avec les données](premier-travail-avec-les-donnees.html), il s'agit du <dfn>tableau de données</dfn><dfn data-index="données, tableau"> ou <dfn lang="en">data frame</dfn> en anglais.

### Propriétés et création

Dans **R**, les tableaux de données sont tout simplement des listes avec quelques propriétés spéficiques :

- les tableaux de données ne peuvent contenir que des vecteurs ;
- tous les vecteurs d'un tableau de données ont la même longueur ;
- tous les éléments d'un tableau de données sont nommés et ont chacun un nom unique.

Dès lors, un tableau de données correspond aux fichiers de données que l'on a l'habitude de manipuler dans d'autres logiciels de statistiques comme **SPSS** ou **Stata**. Les variables sont organisées en colonnes et les observations en lignes.

On peut un tableau de données avec la fonction `data.frame`{data-pkg="base"} :

```{r}
df <- data.frame(
sexe = c("f", "f", "h", "h"),
age = c(52, 31, 29, 35),
blond = c(FALSE, TRUE, TRUE, FALSE)
)
df
str(df)
```

La fonction `data.frame`{data-pkg="base"} a un gros défaut : si on ne désactive pas l'option `stringsAsFactors = FALSE` elle transforme les chaînes de caractères, ici la variable <var>sexe</var> en facteurs (un type de vecteur que nous aborderons plus en détail dans un [prochain chapitre](facteurs-et-vecteurs-labellises.html)).

```{r}
df <- data.frame(
sexe = c("f", "f", "h", "h"),
age = c(52, 31, 29, 35),
blond = c(FALSE, TRUE, TRUE, FALSE),
stringsAsFactors = FALSE
)
df
str(df)
```

Un tableau de données étant une liste, la fonction `length`{data-pkg="base"} renverra le nombre d'éléments de la liste, donc dans le cas présent le nombre de variables et `names` leurs noms :

```{r}
length(df)
names(df)
```

Comme tous les éléments d'un tableau d'un tableau de données ont la même longeur, cet objet peut être vu comme bidimensionnel. Les fonctions `nrow`{data-pkg="base"}, `ncol`{data-pkg="base" data-rdoc="nrow"} et `dim`{data-pkg="base"} donnent respectivement le nombre de lignes, le nombre de colonnes et les dimensions de notre tableau.

```{r}
nrow(df)
ncol(df)
dim(df)
```

De plus, tout comme les colonnes ont un nom, il est aussi possible de nommer les lignes avec `row.names`{data-pkg="base"} :

```{r}
row.names(df) <- c("Anna", "Mary-Ann", "Michael", "John")
df
```

### Indexation

Les tableaux de données étant des listes, nous pouvons donc utiliser les crochets simples (`[]`), les crochets (`[[]]`) et le symbole dollar (`$`) pour extraire des parties de notre tableau, de la même manière que pour n'importe quelle liste.

```{r}
df[1]
df[[1]]
df$sexe
```

Cependant, un tableau de données étant un objet bidimensionnel, il est également possible d'extraire des données sur deux dimensions, à savoir un premier critère portant sur les lignes et un second portant sur les colonnes. Pour cela, nous utiliserons les crochets simples (`[]`) en séparant nos deux critères par une virgule (`,`).

Un premier exemple :

```{r}
df
df[3, 2]
```

Cette première commande indique que nous souhaitons la troisième observation et la seconde valeur, autrement dit l'âge de Michael. Le même résultat peut être obtenu avec l'indexation par nom, l'indexation par condition, ou un mélange de tout ça.

```{r}
df["Michael", "age"]
df[c(F, F, T, F), c(c(F, T, F))]
df[3, "age"]
df["Michael", 2]
```

Il est également possible de ne préciser qu'un seul critère. Par exemple, si je souhaite les deux premières observations, ou les variables <var>sexe</var> et <var>blond</var> :

```{r}
df[1:2,]
df[,c("sexe", "blond")]
```

Il a suffit de laisser un espace vide avant ou après la virgule. ATTENTION ! Il est cependant impératif de laisser la virgule pour indiquer à **R** que l'on souhaite effectuer une indexation à deux dimensions. Si l'on oublie la virgule, cela nous ramène au mode de fonctionnement des listes. Et le résultat n'est pas forcément le même :

```{r}
df[2, ]
df[, 2]
df[2]
```

<div class="note">
Au passage, on pourra noter quelques subtilités sur le résultat renvoyé.

```{r}
str(df[2, ])
str(df[, 2])
str(df[2])
str(df[[2]])
```

`df[2, ]` signifie que l'on veut toutes les variables pour le second individu. Le résultat est un tableau de données à une ligne et trois colonnes. `df[2]` correspond au mode d'extraction des listes et renvoie donc une liste à un élément, en l'occurence un tableau de données à quatre observations et une variable. `df[[2]]` quant à lui renvoie le contenu de cette variable, soit un vecteur numérique de longeur quatre. Reste `df[, 2]` qui signifie renvoie toutes les observations pour la seconde colonne. Or l'<dfn>indexation bidimensionnelle</dfn> a un fonctionnement un peu particulier : par défaut cela renvoie un tableau de données mais s'il n'y a qu'une seule variable dans l'extraction, c'est un vecteur qui est renvoyé. Pour plus de détails, on pourra consulter l'entrée d'aide de `[.data.frame`{data-pkg="base" data-rdoc="Extract.data.frame"}.
</div>

### Afficher les données

Prenons un tableau de données un peu plus conséquent, en l'occurence un jeu de données disponible dans l'extension `questionr`{.pkg} et correspondant à un extrait de l'enquête *Histoire de vie* réalisée par l'INSEE en 2003.
Il contient 2000 individus et 20 variables.

```{r}
library(questionr)
data(hdv2003)
d <- hdv2003
```

Si l'on demande à afficher l'objet `d` dans la console (résultat non reproduit ici), **R** va afficher l'ensemble du contenu de `d` à l'écran ce qui, sur un tableau de cette taille, ne sera pas très lisible. Pour une exploration visuelle, le plus simple est souvent d'utiliser la <dfn>visonneuse</dfn> intégrée à **RStudio** que l'on peut appeller avec la fonction `View`{data-pkg="utils"}.

```{r, eval=FALSE}
View(d)
```


Les fonctions `head`{data-pkg="utils"} et `tail`{data-pkg="utils" data-rdoc="head"}, qui marchent également sur les vecteurs, permettent d'afficher seulement les premières (respectivement les dernières) lignes d'un tableau de données :

```{r}
head(d)
tail(d, 2)
```

L'extension `dplyr`{.pkg}, que nous n'aborderons en détails que [plus tard](introduction-a-dplyr.html), propose une fonction `glimpse`{data-pkg="dplyr"} (ce qui signifie <q>aperçu</q> en anglais) qui permet de visualiser rapidement et de manière condensée le contenu d'un tableau de données.

```{r, message=FALSE}
library(dplyr)
glimpse(d)
```

L'extension `questionr`{.pkg} propose une fonction `lookfor`{data-pkg="questionr"}
qui permet de lister les différentes variables d'un fichier de données :

```{r}
lookfor(d)
```

Lorsque l'on a un gros tableau de données avec de nombreuses variables, il peut être difficile
de retrouver la ou les variables d'intérêt. Il est possible d'indiquer à `lookfor`{data-pkg="questionr"}
un mot-clé pour limiter la recherche. Par exemple :

```{r}
lookfor(d, "trav")
```

Il est à noter que si la recherche n'est pas sensible à la casse (i.e. aux majuscules et aux minuscules),
elle est sensible aux accents.

La méthode `summary`{data-pkg="base"} qui fonctionne sur tout type d'objet permet d'avoir quelques statistiques de base sur les différentes variables de notre tableau, les statistiques affichées dépendant du type de variable.

```{r}
summary(d)
```

On peut également appliquer `summary`{data-pkg="base"} à une variable particulière.

```{r}
summary(d$sexe)
summary(d$age)
```

L'extension `questionr`{.pkg} fournit également une fonction bien pratique pour décrire les
différentes variables d'un tableau de données. Il s'agit de `describe`{data-pkg="questionr"}.
Faisons de suite un essai :

```{r}
describe(d)
```

Comme on le voit sur cet exemple, `describe`{data-pkg="questionr"} nous affiche le type des variables, les premières valeurs de chacune, le nombre de valeurs manquantes, le nombre de valeurs différentes (uniques) ainsi que quelques autres informations suivant le type de variables.

Il est possible de restreindre l'affichage à seulement quelques variables en indiquant le nom de ces dernières.

```{r}
describe(d, "age", "trav.satisf")
```

On peut également transmettre juste une variable :

```{r}
describe(d$sexe)
```

## En résumé

**Les Listes**

- Les listes sont des objets unidimensionnels peuvant contenir tout type d'objets, y compris d'autres listes.
- Elles ont une longueur que l'obtient avec `length`{data-pkg="base"}.
- On créé une liste avec `list`{data-pkg="base"} et on peut fusionner des listes avec `append`{data-pkg="base"}.
- Tout comme les vecteurs, les listes peuvent être nommées et les noms des éléments s'obtiennent avec `names`{data-pkg="base"}.
- Les crochets simples (`[]`) permettent de sélectionner les éléments d'une liste, en utilisant l'indexation par position, l'indexation par nom ou l'indexation par condition. Cela renvoie toujours une autre liste.
- Les doubles crochets (`[[]]`) renvoient directement le contenu d'un élément de la liste que l'on aura sélectionné par position ou par nom.
- Le symbole `$` est un raccourci pour facilement sélectionner un élément par son nom, `liste$nom` étant équivalent à `liste[["nom"]]`.

**Les Tableaux de données**

- Les tableaux de données sont des listes avec des propriétés particulières :
i. tous les éléments sont des vecteurs ;
ii. tous les vecteurs ont la même longueur ;
iii. tous les vecteurs ont un nom et ce nom est unique.
- On peut créer un tableau de données avec `data.frame`{data-pkg="base"}.
- Les tableaux de données correspondent aux fichiers de données que l'on utilise usuellement dans d'autres logiciels de statistiques : les variables sont représentées en colonnes et les observations en ligne.
- Ce sont des objets bidimensionnels : `ncol`{data-pkg="base" data-rdoc="nrow"} renvoit le nombre de colonnes et `nrow`{data-pkg="base"} le nombre de lignes.
- Les doubles crochets (`[[]]`) et le symbole dollar (`$`) fonctionnent comme pour les listes et permettent d'accéder aux variables.
- Il est possible d'utiliser des coordonnées bidimensionnelles avec les crochets simples (`[]`) en indiquant un critère sur les lignes puis un critère sur les colonnes, séparés par une virgule (`,`).

0 comments on commit 4400b6f

Please sign in to comment.