<- "iris" fleur
3 Objets R
3.1 Définition (informelle)
Un objet R est une “boîte étiquetée”, dans laquelle on peut placer une certaine information, autrement dit une certaine valeur.
Plus précisément, il s’agit d’un espace de stockage dans la mémoire de R, auquel on va donner un nom, et que l’on va remplir avec un certain type d’information ou de données. On peut ensuite y accéder à tout moment et réutiliser cette information ou ces données dans le cadre de calculs, de tests, etc.
Ces objets peuvent être de différentes natures : c’est une notion importante car la plupart des fonctions de R (à l’exception des fonctions dites génériques) ne peuvent travailler qu’avec une catégorie précise d’objet, et renverront des erreurs si on leur soumet des objets qui n’appartiennent pas à la catégorie attendue.
3.2 Affectation
En R, l’opérateur d’affectation est symbolisé par une flèche (<-
). Par exemple, pour stocker la chaîne de caractères “iris” dans un objet R (arbitrairement) nommé fleur
, on procède ainsi :
Il est ensuite possible de réafficher à tout moment le contenu de l’objet fleur
avec la fonction print()
:
print(fleur)
[1] "iris"
ou plus simplement en tapant son nom :
fleur
[1] "iris"
3.3 Zoologie des objets R
La plupart des définitions données ci-dessous, bien que restant acceptables, sont un peu simplifiées ou informelles. Pour entrer plus techniquement dans le détail des différents types et des différentes classes d’objets R, on pourra par exemple consulter Wickham et al. (2023), ou Husson et al. (2018), ou simplement le manuel de R.
3.3.1 Motivation
Pourquoi passer un peu de temps sur l’apprentissage (potentiellement peu passionnant) des classes/types d’objets R, et des structures de données ? Consultons par exemple l’aide de la fonction gpagen()
du package {geomorph}
(peu importe son utilité à ce stade !) :
library(geomorph)
help(gpagen)
Arguments
A: Either an object of class geomorphShapes or a 3D array (p x k x n) containing landmark coordinates for a set of specimens. If A is a geomorphShapes object, the curves argument is not needed.
curves: An optional matrix defining which landmarks should be treated as semilandmarks on boundary curves, and which landmarks specify the tangent directions for their sliding. This matrix is generated with readland.shapes following digitizing of curves in StereoMorph, or may be generated using the function define.sliders.
surfaces: An optional vector defining which landmarks should be treated as semilandmarks on surfaces
...
On peut donc voir que cette fonction attend un objet de type “array” pour l’argument A
, un objet de type “matrix” pour l’argument curves
, un objet de type “vector” pour l’argument surfaces
, etc.
Sans une connaissance au moins basique de ce que cela signifie, vous ne pourrez pas fournir à cette fonction les arguments attendus, et donc tout simplement pas l’utiliser. Cela vaut évidemment pour n’importe quelle autre fonction R !
3.3.2 Vecteurs
Un vecteur est une suite indexée de valeurs qui sont toutes de même type : une suite de nombres, de caractères, etc. On peut définir un vecteur avec la fonction c()
:
<- c(2, 5.9, 6.2, 8.3) # définir un vecteur x
x print(x) # afficher x
[1] 2.0 5.9 6.2 8.3
Tous les éléments d’un vecteur étant indexés (numérotés), il est aisé de les sélectionner et d’y accéder :
1] # afficher le premier élément de x x[
[1] 2
3] # afficher le troisième élément de x x[
[1] 6.2
c(1, 2)] # afficher les éléments n° 1 et 2 de x x[
[1] 2.0 5.9
R fournit aussi des outils commodes pour créer des vecteurs numériques. Le raccourci a:b
renvoie tous les entiers compris entre les deux entiers a
et b
:
1:9
[1] 1 2 3 4 5 6 7 8 9
Plus généralement, la fonction seq()
crée des suites de nombres régulièrement espacés :
seq(from = 2, to = 5, by = 0.5)
[1] 2.0 2.5 3.0 3.5 4.0 4.5 5.0
3.3.3 Facteur
Un facteur est la structure de données symbolisant en R une variable qualitative.
<- c("a", "a", "b", "a", "b") # définir un facteur...
fac print(fac) # ... puis l'afficher
[1] "a" "a" "b" "a" "b"
À ce stade, fac
est un vecteur de chaînes de caractères, mais pas encore un facteur. Pour le convertir en facteur :
<- as.factor(fac)
fac print(fac) # noter la différence d'affichage !
[1] a a b a b
Levels: a b
Diverses fonctions utiles sont disponibles pour les facteurs :
levels(fac) # lister les modalités
[1] "a" "b"
nlevels(fac) # obtenir le nombre de modalités
[1] 2
table(fac) # tableau d'effectifs par modalité
fac
a b
3 2
3.3.4 Matrice
Une matrice est un tableau bidimensionnel constitué de valeurs toutes de même nature : des nombres, des caractères, etc. Chaque valeur est indexée par son numéro de ligne et son numéro de colonne.
## Définir une matrice de deux colonnes :
<- matrix(c(1, 2, 3, 4), ncol = 2)
M print(M)
[,1] [,2]
[1,] 1 3
[2,] 2 4
Remarque : notez que les valeurs sont remplies colonne par colonne. Comment peut-on les remplir plutôt ligne par ligne ? Pour le savoir, consulter l’aide de la fonction matrix()
en tapant help(matrix)
.
Pour accéder aux valeurs d’une matrice donnée :
1, 2] # la valeur en ligne 1 et colonne 2 M[
[1] 3
1] # le contenu de toute la colonne 1 M[,
[1] 1 2
2, ] # le contenu de toute la ligne 2 M[
[1] 2 4
3.3.5 Dataframe
Un data frame est le format usuellement donné par R aux jeux de données que l’on importe depuis un fichier. Il s’agit d’un tableau de données bidimensionnel (“à plat”) à \(n\) lignes (1 ligne = 1 individu) et \(p\) colonnes (1 colonne = 1 variable).
Contrairement à une matrice, la nature des colonnes, i.e. des variables, peut être hétérogène : il peut y avoir des facteurs, des variables numériques, des dates, …, dans le même data frame.
En revanche, comme dans le cas des matrices, chaque valeur est repérée par son numéro de ligne et de colonne : si le data frame s’appelle df
, l’instruction df[2, 3]
permet d’accéder à la valeur de la 3e variable du 2e individu.
3.3.6 Liste
Une liste est un objet unidimensionnel très général permettant de stocker des informations de type potentiellement différent : le premier élément peut être un vecteur numérique, le deuxième une chaîne de caractères, le troisième une matrice, etc.
Pour créer une liste, on utilise la fonction list()
:
<- list("a", 1:5, M) L
Pour accéder au \(k\)-ième élément d’une liste nommée L
, on utilise une notation en double crochet, L[[k]]
:
2]] L[[
[1] 1 2 3 4 5
3.3.7 Autres stuctures
Il existe encore bien d’autres catégories d’objets en R : par exemple, les arrays mentionnés plus haut dans l’exemple introductif, ou de très nombreuses structures spécifiques à un package R en particulier. Nous avons néanmoins ici fait le tour des plus courantes et des plus utiles en pratique.
3.4 Modifier un objet R déjà créé
Contrairement à certains autres langages de programmation (dits “fortement typés”), on peut changer le type d’un objet R après sa création, sous réserve que l’opération garde du sens.
Par exemple, si les chiffres 1 et 2 n’indiquent pas des données numériques mais l’appartenance à des groupes numérotés 1 et 2, on peut souhaiter convertir un vecteur numérique contenant uniquement des 1 et des 2 en un facteur. On peut aussi convertir un data frame en une matrice, etc. On utilise alors la famille de fonctions as.factor()
, as.matrix()
, as.data.frame()
, …
Par exemple :
<- c(1, 2, 1, 2, 2)
x print(x)
[1] 1 2 1 2 2
as.factor(x)
[1] 1 2 1 2 2
Levels: 1 2
3.5 Résumé
Résumons donc les notions principales introduites jusqu’ici :
- Pour affecter une certaine valeur à un objet
x
, on utilise l’opérateur d’affectation :x <- ...
- On peut afficher le contenu de l’objet
x
dans la console en exécutant simplementx
(ouprint(x)
qui a le même effet). - Les objets R sont indexés : on peut accéder à un ou plusieurs éléments de
x
en précisant leur indexation entre crochets. - La classe d’un objet est une caractéristique “flottante”, modifiable. Il existe des fonctions pour convertir un objet vers une nouvelle classe (sans en modifier le contenu), afin qu’il soit traité différemment.
3.6 Opérations élémentaires sur des vecteurs
Terminons par quelques manipulations très élémentaires sur les objets R les plus simples : les vecteurs.
On se propose de saisir et d’étudier les notes (sur 20) de 4 étudiants :
<- c(10, 12, 8, 10) # définir un vecteur de notes
x mean(x) # calculer la moyenne de x
[1] 10
length(x) # nb de valeurs dans x
[1] 4
max(x) # maximum de x
[1] 12
On saisit deux nouvelles notes dans un nouveau vecteur y
, puis on fusionne tout en une seule série de notes z
:
<- c(9, 14) # deux nouvelles notes
y <- c(x, y) # z = concaténation de x et y
z print(z) # afficher z
[1] 10 12 8 10 9 14
1:3] # afficher les 3 premières notes z[
[1] 10 12 8
-3] # afficher tous les éléments de z sauf le n°3 z[
[1] 10 12 10 9 14
On peut également afficher un tri de z
par ordre croissant :
sort(z) # tri croissant par défaut
[1] 8 9 10 10 12 14
Exercice : comment trier z
par ordre décroissant ?
Notons qu’en R, toutes les opérations arithmétiques sont vectorisées, i.e. s’appliquent à toutes les composantes d’un vecteur donné :
/2 # afficher les notes, mais sur 10 z
[1] 5.0 6.0 4.0 5.0 4.5 7.0
Enfin, on peut rattacher les noms des étudiants aux valeurs de z
en attribuant des noms aux différentes composantes du vecteur :
names(z) <- c("Jim", "Eva", "Ana", "Dan", "Ron", "Leo")
print(z)
Jim Eva Ana Dan Ron Leo
10 12 8 10 9 14
L’intérêt est alors de pouvoir accéder aux valeurs de z
par leur nom plutôt que par leur index, ce qui est bien plus naturel :
"Ana"] z[
Ana
8