R, l'application universelle de statistiques

LE logiciel R est un logiciel libre d'analyse statistique de données, qui contient énormément d'extensions (bibliothèques) à des fins très diverses. Cette page est écrite en vue de faciliter la prise en main pour une personne n'ayant aucune connaissance de programmation. En cas de besoin urgent de fréquences et de tableaux croisés à partir d'une table de données existante, voyez plutôt le logiciel libre PSPP, après un éventuel détour par le chapitre Importation et exportation des données, que PSPP gère moins bien.

Page commencée en août 2018 – ajouts sporadiques.

0. Prise en main

0.1 En mode console
0.2 Interface graphique

1. Syntaxe et structures

1.1 Syntaxe
1.2 Booléens et opérateurs logiques
1.3 Conditions if et switch
1.4 Boucles while, repeat et for
1.5 Fonctions-utilisateurs

2. Variables, types et opérateurs

2.1 Nombres
2.2 Chaînes
2.3 Expressions régulières (regex)
2.4 Listes

3. Vecteurs et distributions

3.1 Vecteurs
3.2 Génération de vecteurs
3.3 Modification de vecteurs
3.4 Facteurs
3.5 Distributions

4. Matrices

5. Tables de données

6. Entrées et sorties

6.1 Clavier et console
6.2 Fichiers de simple texte
6.3 Tables textes (csv et tsv)
6.4 Tables binaires (rds et rda)
6.5 Importation et exportation

7. Divers

7.1 système de fichiers

8. Sortie graphique

8.1 plot()
8.2 ggplot() + geom_…()

9. Bibliothèques

0. Prise en main

Pour disposer de R sur un système UNIX, il faut installer le paquet r-base, qui installera les paquets complémentaires. Sur GNU/Linux Debian10-Buster, 76 nouveaux paquets, 107Mo téléchargés et 321 installés.

Sur un système Unix, de la documentation (en anglais) est disponible en Unix, sept fichiers HTML (totalisant 3Mo) sont installés à l'adresse /usr/share/doc/r-doc-html/manual/ et /usr/share/R/doc/manual.

0.1 En mode console

En Unix, le mode interactif de R est lancé par la commande R (nécessairement en majuscule) dans une console. On en sort avec la commande q()

help.start() affiche dans un navigateur le fichier R-intro.html du répertoire /usr/share/R/doc/manual.

En mode interactif, l'invite > apparaît, écrire et saisir avec [Enter] inscrit une réponse sur la ou les ligne(s) suivante(s), ou un message d'erreur :

>
2+2 ; 2+"2"
[1] 4
Error in "2" + 2 : argument non numérique pour un opérateur binaire

…ce qui signifie qu'il est interdit d'additionner le caractère "2" à la valeur numérique 2.

Le mode console peut être utile pour tester une fonction, effectuer un calcul ou réaliser une tâche simple (importation d'un fichier pour l'exporter dans une autre format), mais est peu pratique pour des tâches complexes ou répétitives.

On quitte le mode interactif avec quit()

L'autre façon d'utiliser R est d'éditer un fichier de commandes (un script) dans un éditeur de fichier (notepad++, atom, gedit, kedit, kwrite, pluma…) et le lancer dans une console. Il faut veiller à ce que le script soit lancé à son adresse réelle : en UNIX, si le script essai.r est sauvegardé à l'adresse /home/toto/R/script/, il sera lancé dans une console par :

$ Rscript /home/toto/R/script/essai.r

Il faut évidemment que les éventuels fichiers de données appelés par le script et que toutes les bibliothèques nécessaires soient présentes sur le système et correctement libellés.

Pour automatiser le lancement en Unix et dérivés (double clic sur fichier, ./monfichier.R ou chemin/monfichier hors du répertoire), indiquer #! /usr/bin/Rscript sur la premier ligne de monfichier.R (ou toute autre adresse où se trouve Rscript, chercher avec whereis Rscript dans une console):

#! /usr/bin/Rscript

exp(3)

En mode console, le résultat sera [1] 20.08554

Les éventuels arguments passés par ./Rscript.R 3 seront récupérés sous forme d'un vecteur de chaînes de caractères par commandArgs(TRUE), nécessitant éventuellement as.numeric() pour les transformer en nombres :

#! /usr/bin/Rscript

arguments <- commandArgs(TRUE)
exp(as.numeric(arguments[1])) # 1 désigne le premier ou l'unique argument

0.2 Interface graphique

Plusieurs interfaces graphiques existent en UNIX, Windows ou Mac, comme Rcmdr (paquet r-cran-cmdr dans la distribution GNU/Linux Debian). Pour débuter, Rcmdr semble plus simple. Sur GNU/Linux Debian10-Buster, 168 nouveaux paquets, 119Mo téléchargés et 350 installés.

Pour la première fois, il est peut-être nécessaire de lancer R dans une console en mode super-utilisateur :

#En mode superutilisateur :
su + mot de passe
R

Une fois dans R, frapper la commande suivante et [Enter] :

>
library(Rcmdr)

Les bibliothèques (library) dont Rcmdr a besoin seront demandées. Soit vous en disposez dans un répertoire particulier, auquel cas vous pouvez fournir le nom du répertoire dans une boîte de dialogue, soit elles seront téléchargées et installées avec les droits de superutilisateur.

Une dépendance, gdl, refuse d'être installée (configure: error: missing required header GL/gl.h, problème récurrent en Debian 9 et 10). L'installation sur le système des paquets r-cran-rgl et libglu1-mesa-dev devrait résoudre le problème.

Rcmdr présente deux fenêtres : celle du haut permet la saisie de commande ou de calcul (Rscript), le bouton Soumettre interprète la ligne où se trouve le curseur ou la partie surlignée à la souris et en donne la solution dans la fenêtre du bas. Un fichier Rmarkdown est généré, visualisable dans la fenêtre du haut.

Par défaut, seuls les données sous la forme Rdata, rda… Pour d'autres formats de fichiers, il faut passer par une importation, voir la bibliothèque foreign.

Il y a aussi Rstudio (Affero GPL, entre 120 et 150Mo selon la distribution GNU/Linux).

1. Structures

1.1 Syntaxe

Tout langage a ses règles. Voici les principales du langage R.

> représente l'invite (prompt, attente de commande) de R dans une console ou dans la fenêtre interactive de Rstudio. Il est représenté en bleu dans les exemples ; vous ne devez jamais saisir ce signe vous-même dans une console ni les utiliser dans les scripts.

# permet un commentaire : tout ce qui se trouve à droite du croisillon (hashtag) ne sera pas pris en compte par R dans sa lecture du script.

Est une expression numérique tout agrégat de chiffres, éventuellement précédé du signe - et pouvant contenir un signe . avant son éventuelle partie décimale, un e ou E avant un éventuel ordre de grandeur (exposant de 10), et i comme suffixe de la partie imaginaire ; ou toute expression algébrique valable ou résultat valide d'une fonction arithmétique. Exemples : -443, 2 +5 *(3 -2), 9 ^3, sqrt (43), 3.14, 7.8e9 (7 800 000 000), 7 -i5

Est une chaîne tout agrégat de caractères (chiffres ou non) entourés de guillemets "doubles" ou 'simples', ou résultat valide d'une fonction retournant des chaînes de caractères.

Est une variable tout agrégat de lettres, de chiffres et soulignés _ mais commençant toujours par une lettre, ou une fonction si l'agrégat est suivi de parenthèses. Contrairement aux autres langages de programmation, le signe préconisé pour affecter une valeur à une variable ou du code à une fonction est <- (le signe = fonctionne également, mais est déconseillé).

Note :

, la virgule sépare les paramètres dans les fonctions et les données dans les variables composées.

; sépare opérations ou commandes sur une même ligne.

( ) les parenthèses sont utilisées dans les expressions algébriques, elle contiennent également les paramètres des fonctions écrites par l'utilisateur, des conditions et boucles. Les paramètres nommés utilisent le signe = comme dans l'expression sep="-" de l'exemple cat(c("a", "b"), sep="-").

[ ] les crochets contiennent le rang d'une valeur d'un vecteur ou la ligne, la rangée ou la cellule d'une matrice ou d'une table de données.

{ } les accolades contiennent le code des structures : les fonctions écrites par l'utilisateur, les boucles et conditions.

1.2 Booléens et opérateurs logiques

L'algèbre booléenne étant essentiellement utile pour les conditions et les boucles, elle est présentée avant celles-ci.

TRUE (ou T) et FALSE (ou F) sont les valeurs «booléennes» VRAI et FAUX. class=() et is() permettent de s'assurer qu'une expression est booléenne :

>
boo <- 5 !=4 ; class(boo) ; is(boo)
[1] "logical"
[1] "logical" "vector"

Tout nombre non nul est vrai, et 0 est faux, mais une chaîne vide ou non ne peut servir de booléen comme c'est souvent le cas dans d'autres langages.

Ces valeurs sont générées par les opérateurs suivants (x et y représentent des nombres ou des chaînes) :

x == y retourne TRUE si x et y sont égaux ; FALSE sinon
x != y retourne TRUE si x et y sont différents ; FALSE sinon

x < y retourne TRUE si x est strictement inférieur à y ; FALSE sinon
x > y retourne TRUE si x est strictement supérieur à y ; FALSE sinon
x <= y retourne TRUE si x est inférieur ou égal à y ; FALSE sinon
x >= y retourne TRUE si x est supérieur ou égal à y ; FALSE sinon

x %in% y retourne TRUE si la chaîne ou le nombre x est un élément du vecteur y ; FALSE sinon

Notes :

x & y ou x && y : «ET logique» : retourne TRUE si x et y sont tous les deux vrais ; FALSE sinon
x | y ou x || y : «OU logique» : retourne TRUE si au moins l'un des deux de x ou y sont vrais ; FALSE sinon
xor(x, y) : «OU exclusif» un seul TRUE donne TRUE ; deux TRUE ou deux FALSE donnent FALSE
! x inversion logique : ! T est FALSE et ! F est TRUE

Ces opérateurs permettent des compositions, parfois avec des parenthèses :

3 == 3 | 2 > 3 # TRUE ou FALSE : vrai
! (3 == 3 | 2 > 3) # l'inverse de TRUE ou FALSE : faux

1.3 Conditions if et switch

Les conditions et les boucles sont des structures qui permettent d'exécuter un code ou des portions de code selon l'évaluation d'une expression logique (une condition). Les conditions sont écrites (entre parenthèses) après le mot-clé de la structure (if, while, for…), le code est écrit { entre accolades }.

Condition if

La première structure est la condition. Seul le if (condition) { code } est indispensable. L'éventuel else if (condition) { code } est une condition alternative (il peut y en avoir plusieurs) qui ne sera testée que si celle du if n'a pas été rencontrée. L'éventuel else { code } (sans condition) vaut pour tous les autres cas, c'est-à-dire si aucune des conditions de if ou else if n'est remplie.

n <- 3
if (n < 5) {
  print("moins que 5")
} else if (n > 7) {
  print("plus que 7")
} else {
  print("égal à 5, 6 ou 7")
}

Notes

Fonction switch

Permet de choisir dans une liste l'item qui correspond à une valeur, numérique ou non (contrairement aux autres structures il n'y a ni condition entre parenthèses ou code entre accolades, la condition est ici plus implicite, il s'agit d'une concordance entre une chaîne et sa position). Dans l'exemple suivant, c'est un nombre qui désigne l'index de la chaîne à renvoyer (1 pour la deuxième position, 2 pour la troisième…)

>
lequel <- 2 ; switch(lequel, "rouge", "vert", "bleu")
[1] "vert"

La position ne doit pas nécessairement être une expression numérique, mais peut être une étiquette arbitraire sous forme de (courte) chaîne (l'appel par position reste possible) :

>
quoi <- "C" ; switch(quoi, "M"="magenta", "J"="Jaune", "C"="cyan")
[1] "cyan"

Un appel à une fonction est également possible :

>
>
carmin <- function() { print("OK") }
lql <- "c" ; switch(lql,  switch("c", "m" ="mauve", "g" ="gris", "c" =carmin())
[1] "OK"

1.4 Boucles while, repeat et for

Boucle while

Une boucle while est une portion de code parcourue et répétée tant que la condition d'entrée est maintenue.

n <- 0
while (n < 7) {
   print(n)
   n <- n +1
}

Il n'est cependant pas interdit de prévoir une condition de sortie prématurée avec break (l'exemple donne la suite de Fibonacci limitée à 1 000) :

n0 <- 1 ; n1 <- 1
while (TRUE) {
  print(n0)
  n <- n0 +n1 ;
  n0 <- n1 ; n1 <- n
  if (n1 >1000) { break }
}

Il est possible d'éviter une partie de la boucle avec next, qui renvoie directement en début de boucle. Dans cet exemple, next permet d'éviter l'expression 1 /0 (Inf), qui peut se révéler problématique.

n <- -4
while (n < 3) {
  n <- n +1
  if (n ==0) { next }
  print(1 /n)
}

Boucle repeat

Une boucle repeat est une boucle éternelle dont on ne peut sortir qu'avec break, souvent déclenché selon une condition. Cette boucle s'arrêtera au premier nombre divisible par 7 et 13 (voir l'opérateur modulo)

n <-0
repeat {
  n <- n +1
  print(n)
  if (n %%7 ==0 & n %%13 ==0) { break }
}

Note :

Boucle for

La boucle for se base sur une itération, la récursion d'une collection d'objets représentés successivement par la même variable. L'exemple suivant affiche quatre mots joignant les initiales A, g, p et t à rès.

for (x in c("A", "g", "p", "t")) {
  print(paste(x, "rès", sep=""))
}

Cette boucle peut également utiliser une séquence de nombres :

for (i in 0:10) {
  print(i ^2)
}

Il est possible d'imbriquer plusieurs boucles. La nom de la variable de récursion de la boucle incluse doit être différente du nom de la première :

for (i in 1:10) {
  print(paste("Table de", i, ":"))
  for (j in 1:10) {
    print(paste(i, "x", j, "=", i*j))
  }
}

Notes

1.5 Fonctions «utilisateurs»

Une fonction-utilisateur est une portion de code écrit et que l'on peut appeler d'un ou de plusieurs endroits du script. Cela peut économiser de la place ou simplement décharger le script de calculs fastidieux et le rendre plus clair. Les fonctions peuvent même être sauvegardées dans un autre fichier, chargé en cas de besoin avec la commande source("chemin/vos_fonctions.R").

Supposons que l'on ait besoin de calculer l'hypoténuse d'un triangle rectangle à partir de la longueur des deux autres côtés (formule h² = a² + b²) :

# définition de la fonction
hypotenuse <- function (x, y) {
  return (sqrt (x^2 + y^2)) # l'hypoténuse est la racine carrée de la somme des carrés des deux autres côtés
}

# appels de la fonction
x <- 37 ; y < 41
print(hypotenuse (3, 4))
print(hypotenuse (12, 5))
# interrogation des valeurs de x et y
print (x) ; print (y)

Explications et notes :

Une fonction ne renvoie pas nécessairement de valeurs, mais peut s'occuper (en autres choses) de leur affichage, ou de leur sauvegarde dans un fichier :

hypotenuse <- function(x, y) {
  cat("L'hypoténuse d'un triangle rectangle de côtés",
      x, "et", y, "vaut", sqrt(x^2+y^2), "\n")
}
hypotenuse(3, 4)
hypotenuse(12, 5)

Les deux variances

Comme la fonction var() de R est la «variance non biaisée» d'un échantillon, la somme des écarts à la moyenne au carré est divisée par n-1 et non par n. En cas de besoin récurrent de la variance «empirique» (celle d'une population), il est possible de la calculer soi-même par une fonction utilisateur. Ceci à titre d'exemple, car il suffit de multiplier la variance non biaisée par (n-1)/n pour trouver la variance empirique.

var_n <- function(x) {
  moyenne <- sum(x) / length(x) # calcul de la moyenne
  acc <- 0 # initialisation de la variable d'accumulation des carrés des distances
  for (i in x) {
    acc <- acc + (i-moyenne)^2 # écarts à la moyenne au carré pour chaque valeur
    }
  acc /length(x) # division par n # sans return : cette dernière expression est renvoyée
  }

dist <-c(1, 5, 6, 2, 4, 5)

print(var_n(dist)) # variance "n" pour un groupe complet
print(var(dist))   # variance "n-1" en cas d'échantillon

Une fonction peut en appeler une autre

Le but des fonctions étant d'organiser et de raccourcir un script, une fonction écrite par l'utilisateur peut faire appel à une autre de ces fonctions :

# première fonction, songez à documenter ce que vous faites!
var_n <- function(x) {
  moyenne <- sum(x) / length(x) # calcul de la moyenne
  acc <- 0                      # initialisation de la variable d'accumulation
  for (i in x) {
    acc <- acc + (i-moyenne)^2  # écarts à la moyenne au carré pour chaque valeur
    }
  acc / length(x)                  # division par n
  }

# deuxième fonction, appelant la première
sd_n <- function(x){
  sqrt(var_n(x))   # l'écart type (standard deviation) est la racine carrée de la variance
}

dist <-c(1, 5, 6, 2, 4, 5, 2, 7)
print(sd_n(dist))    # écart-type d'une population
print(sd(dist))      # écart-type d'un échantillon

Récursivité

Une fonction peut s'appeler elle-même (récursivité), à condition de prévoir une condition de sortie :

factorielle <- function (x) {
  if (x > 1) {           # si le nombre est plus grand que 1
    x *factorielle (x -1)   # il faut le multiplier à la factorielle x-1
  }
  else {
    1  # en fin de compte, le calcul sera : x*(x-1)*(x-2)*…*1
  }
}
for (i in 0:10) {
  cat (paste (i, "!", sep=""), "=", factorielle (i), "\n")
}

Il est possible de sauvegarder les fonctions qu'on a écrites dans un fichier, à importer dans un script avec source() :

source("/home/toto/R/mesfonctions.R")
sd_n(c(2, 3, 5, 5, 6, 2, 4, 3))

Opérateurs binaires «utilisateur»

Il est possible de définir de nouveaux opérateurs binaires, nécessairement entourés de %. Pour définir %~% comme opérateur «presqu'égal» (c'est-à-dire que leur différence ne peut dépasser, par exemple, le dixième de la quantité du plus grand) :

"%~%" <- function(a, b){
  if (abs(a-b) /max(a, b) <= 0.1) {
    return(TRUE)
  }
  else {
  return(FALSE)
  }
}
8 %~% 9 ; 9 %~% 10

2. Variables, types et opérateurs

En R, les variables peuvent être :

class() et is() permettent de connaître le type d'une variable.

2.1 Nombres

Voir 2. Variables pour les généralités sur les variables.

L'assignation d'une valeur à une variable se fait par <- :

x <- 43 affecte la valeur numérique 43 à la variable x
x <- 43L précise qu'il s'agit d'un nombre entier
a <- 12.3e-8 est la notation scientifique : le «réel» 12,3 multiplié par 10-8
x <- 4 + 3i permet l'affectation d'un nombre complexe

>


>



>
x <- 3 ; class(x) ; is(x)
[1] "numeric"
[1] "numeric" "vector"
y <- 4L ; class(y) ; is(y)
[1] "integer"
[1] "integer"             "numeric"             "vector"
[4] "data.frameRowLabels"
z <- 5 +6i ; class(z) ; is(z)
[1] "complex"
[1] "complex" "vector"

as.numeric() transforme une expression (éventuellement sous forme de chaîne) en nombre
as.double() semble un synonyme de as.numeric()
as.integer() transforme une expression (éventuellement sous forme de chaîne) en nombre entier

Les trois fonctions précédentes ne gardent pas la partie imaginaire d'une expression numérique et transforme une chaîne imaginaire en NA. Pour traiter valablement les nombres complexes :

>
as.complex("4 +3i")
4+3i

+, -, *, / s'organisent entre eux comme appris à l'école. Pour changer l'ordre de préséance entre les opérateurs, il faut utiliser les parenthèses : 3*5-7/4 n'égale pas 3*(5-7)/4

^ ou ** est l'opérateur exposant : 7 **3 donne 343
sqrt() donne la racine carrée d'une expression numérique :

>
sqrt(141)
[1] 11.87434

43 valant 2 *17 +9,

Inf (et -Inf), majuscule obligatoire! est le réponse à certains calculs, comme 1 /0, mais pas tan(pi /2) qui vaut 1.633124e+16 à cause de l'imprécision sur pi

NA est la réponse à certaine fonctions as.numeric("4 +3i")

NaN est la réponse à certains calculs, comme sqrt(-141), ou aux indéterminées comme -Inf /Inf, Inf -Inf, 0 /0 et 0 *Inf

Pour R, 0 **0 égale 1.

abs(n) retourne la valeur absolue (abrogation du signe négatif)
sign(n) retourne 1 ou -1 selon le signe de n, 0 si n ==0

min(x, y, z) retourne la valeur minimale entre deux ou plusieurs valeurs
max(x, y, z) retourne la valeur maximale entre deux et plusieurs valeurs

floor() arrondit par défaut
ceiling() arrondit par excès
round(reel) arrondit au nombre entier le plus proche, au nombre entier pair le plus proche s'il se termine par .5

>
round(2.5) ; round(3.5)
[1] 2
[1] 4

round(reel, n) arrondi à n décimales si n est positif, à 10abs(n) près s'il est négatif :

>
round(3.14159, 4) ; round(73826, -3)
[1] 3.1416
[1] 74000

exp(n) retourne la valeur de e (environ 2.718282) exposant n
log(n) retourne le logarithme naturel/népérien du nombre n
log1p(n) retourne le logarithme népérien du nombre n+1

log10(n) et log2(n) retournent les logarithmes en base 10 et 2.

pi contient la valeur 3.141593
cos(n) retourne la valeur du cosinus d'un angle exprimé en radian
sin(n) retourne la valeur du sinus d'un angle exprimé en radian
tan(n) retourne la valeur de la tangente d'un angle exprimé en radian

Pour exprimer une valeur en degrés, la multiplier par pi/180 :

>
cos(60 *pi/180)
[1] 0.5

2.2 Chaînes de caractères

Tout agrégat de caractères écrit entre guillemets est une chaîne de caractères. Si les guillemets entourant sont simples, la chaîne peut contenir des guillemets doubles et vice-versa. Il est encore possible, dans une chaîne entourée de guillemets doubles, d'écrire d'autres guillemets doubles en les précédant d'une barre inverse :

ch <- "C'est une chaîne de caractères"
uneautre <- 'Encore une telle "chaîne"!'
lamême <- "Encore une telle \"chaîne\"!"

Notes

class() renvoie le type de donnée d'une variable :

>
class("darla") ; is("dirladada")
[1] "caracter"
[1] "character"    "vector"   "data.frameRowLabels"
[4] "SuperClassMethod"

is.character("Lundi") retourne TRUE puisque "Lundi" est une chaîne.
as.character(43) transforme le nombre 43 en chaîne de caractères "43"

nchar("Lundi") retourne le nombre de caractères d'une chaîne (et non length()!)

min("bn", "jh") retourne "bn", la chaîne arrivant en premier selon le classement alphabétique parmi deux ou plusieurs chaînes
max("bn", "zb", "jh") retourne "zb", la chaîne arrivant en dernier selon le classement alphabétique parmi deux ou plusieurs chaînes

C'est l'ordre ASCII qui prévaut (" ", "!", "+"…) mais les lettres accentuées sont égales aux non accentuées, sauf en cas d'égalité pour le reste des deux chaînes :

min("bex", "bépo") retourne "bépo" ("e" et "é" équivalents : "p" avant "x")
max("besicles", "bésicles") retourne "besicles" (égalité pour les autres)

"bex" < "bépo" retourne FALSE puisqu'arrivant après selon l'ordre alphabétique

paste()

paste("dirla", "dada") concatène deux (ou plusieurs) chaînes, avec espace intercalaire (par défaut) : "dirla dada"
paste("dirla", "dada", sep="-") concatène deux (ou plusieurs) chaînes, avec une expressions intercalaire : "dirla-dada"
paste("dirla", "dada", sep="") ou paste0("dirla", "dada") concatène deux (ou plusieurs) chaînes, sans espace intercalaire : "dirladada"
paste(4, "2", 1, sep ="") renvoie la chaîne "421", les nombres étant convertis en chaînes

Notes : paste() ne sert pas à assembler les éléments d'un vecteur en une seule chaîne, mais à assembler chaque élément du vecteur avec autre chose :

>
vec <- c("z", "a", "d") ; ch <- paste(vec, "bis") ; print(ch) ; nchar(ch)
[1] "z bis" "a bis" "d bis"
[1] 5 5 5

Il est possible de concaténer un à un les éléments de deux vecteurs. S'ils ont différentes longueurs, le plus court est recouru à nouveau jusqu'à atteindre la fin du plus long :

>
vec1 <- c("a", "b", "c") ; vec2 <- 1:5 ; paste(vec1, vec2)
[1] "a 1" "b 2" "c 3" "a 4" "b 5"

Pour obtenir une vraie chaîne (d'un seul tenant) à partir d'un vecteur, il faut utiliser str_flatten() de la librairie stringr :

>
library(stringr) ; vec <- c("z", "a", "d") ; ch <- str_flatten(vec) ; print(ch) ; nchar(ch)
[1] "zad"
[1] 3

Vecteurs utiles pour les chaînes

letters[n] donne la nième minuscule de l'alphabet
LETTERS[n] donne la nième majuscule de l'alphabet

LETTERS[18:20] retourne "R" "S" "T" (de la 18e lettre : "R", à la 20e : "T" de l'alphabet latin majuscule
letters[10:12] retourne de la même manière "l" "j" "k"

toupper() renvoie une chaîne en majuscules
tolower() renvoie une chaîne en minuscule

abbreviate("Organisation Nations Unies") retourne "ONU"

substr(chaîne, n1, n2) retourne une partie de la chaîne d'origine, d'un rang à un autre :

>
substr("socialisme", 3, 5)
[1] cia

Rechercher

grep() recherche une chaîne de caractères ou une liste de chaînes :
grep("é", c("un", "tramway", "nommé", "désir")) renvoie 3 4, soit le rang des éléments du vecteur dans lesquels se trouve un é .

grepl("é", c("désir", "intense")) renvoie True False puisque le caractère é se trouve dans la première chaîne et non dans la seconde. Le vecteur peut être remplacé par une chaîne.

regexpr("é", "désir") renvoie le premier rang de la chaîne où commence l'expression é, 2 en l'occurrence ; -1 dans le cas négatif.

gregexpr("a", "abracadabra") est plus complexe, renvoyant une liste composite. unlist(gregexpr("a", "abracadabra")) renvoie 1 4 6 8 11 , soit un vecteur des rangs de la chaîne occurrences de "a" ou NULL si aucune occurrence

unlist(regexec(motif, chaine)) est similaire à regexpr(), renvoyant le rang de la première occurrence du motif dans chaine ; -1 sinon

Remplacer

gsub(ch1, ch2, chaine, fixed=True) dans une chaîne, remplace systématiquement ch1 par ch2 :

>
gsub("r", "ch", "rats roux")
[1] "chats choux"

sub() ne s'occupe que de la première occurrence de la sous-chaîne :

>
sub("r", "ch", "rats roux")
[1] "chats roux"

Note : (parfois!) la chaîne à rechercher pour gsub est considérée comme une expression régulière. Pour la recherche d'une simple chaîne de caractères, terminer avec fixed=TRUE.

Découper

strsplit("les sanglots longs des violons de l'automne, " ") découpe la chaîne à chaque espace :

[1] "les" "sanglots" "longs" "des"
[5] "violons" "de" "l'automne"

Attention : cette fonction produit une liste, qui a pour longueur 1. Pour produire un vecteur, il faut passer par unlist() :

>
vec <- unlist(strsplit("abracadabra", "cada")) ; vec ; length(vec)
[1] "abra" "bra"
[1] 2

strsplit("abracadabra", "") détache chaque lettre (il y a un vide entre chaque lettre)

strsplit("Oui. Non. Peut-être", ".", fixed=T) à essayer sans fixed=T!

Attention : si le motif de découpe est situé en début de la chaîne à découper, le premier élément du vecteur généré est une chaîne vide ; s'il est situé en fin de chaîne, aucun élément vide n'est généré :

>
strsplit("rêver", "r")
[1] "" "êve"

2.3 Expressions régulières (regex)

Les expressions rationnelles, ou régulières, permettent de raffiner les recherches et remplacements de (groupes) de lettres dans une chaîne. Il s'agit d'une amélioration du système des jokers ? et * utilisés dans les recherches de fichiers. D'autres pages de ce site en parlent également, mais il faut savoir que chaque langage peut présenter des variantes et des lacunes. Un exemple simple d'une expression régulière est de séparer une chaîne à chaque chiffre ("\\d") :

ch <- "nouvelle5chanson13française" ;
if (regexpr("\\d", ch) > -1)
  {
  unlist(strsplit(ch, "\\d")) ;
  }
[1] "nouvelle" "chanson" "" "française"

Par défaut, sub(), gsub(), strsplit(), grep(), grepl, regexpr et gregexpr utilisent les expressions régulières dans les chaînes de recherche. Il faut spécifier fixed=T pour que les caractères de la chaîne soient pris tels quels.

. (un point) désigne n'importe quel caractère :

^ début de phrase (mais également exclusion dans une expression [], voir juste ci-après)
$ fin de phrase

[] permet plusieurs choix pour un seul caractère :

() permet de choisir (avec |) entre deux ou plusieurs (groupes de) caractères ou de considérer un groupe de caractères (également utile pour les quantificateurs ?, + , * et {}) :

? rend optionnel le dernier (groupe de) caractère(s) :

+ permet une répétition indéfinie du dernier (groupe de) caractère(s) :

* combine ? et + : rien, 1 ou une répétition indéfinie du dernier (groupe de) caractère(s) :

Par exemple, rou(dou)* désigne aussi bien "rou" que "roudou", "roudoudou"…

{n} permet la répétition exacte n fois d'un (groupe de) caractère(s). Comparer :

En ajoutant ? après ? + * {} , la demande devient plus parcimonieuse (non greedy) :

\\ permet à un caractère normalement utilisé pour le codage de conserver sa valeur initiale, ainsi que de coder des types de caractères :

Notes : dans les autres langages, l'antislash n'est pas redoublé : c'est une spécificité de R.

Remplacement dans une chaîne

sub("[a-e]", "b", "ssessascs") retourne "ssbssascs", à savoir remplace par "b" la première lettre "a", "b", "c", "d" ou "e" trouvée dans la chaîne "ssessass" par "b".
gsub("[a-e]", "b", "ssessass") retourne "ssbssbsbs", à savoir remplace par "b" toutes les lettres "a", "b", "c", "d" ou "e" trouvée dans la chaîne "ssessass".

Pour éviter que la chaîne de recherche soit interprétée comme une expression régulière dans les fonctions sub(), gsub(), strsplit(), grep()… il faut introduire fixed=T :

Découpage de chaîne

strsplit("fichier.txt", ".") retourne "" "" "" "" "" "" "" "" "" "" "" (chaque lettre occasionne une coupure : il n'y a que du vide entre elles)
strsplit("fichier.txt", ".", fixed=T) retourne "fichier" "txt"
strsplit("fichier.txt", "\\.") fonctionne également

semaine <- c("Lun", "Mar", "Mer", "Jeu", "Ven", "Sam", "Dim") ; charmatch("Jeu", semaine) retourne 4

unique(c("a", "b", "a", "a", "b", "c", "a")) supprime les doublons : "a" "b" "c"

make.unique(c("a", "b", "a", "a", "b", "c", "a")) retourne "a" "b" "a.1" "a.2" "b.1" "c" "a.3" : différence est faite entre les différentes entrées de même valeur.

table(c("a", "b", "a", "a", "b", "c", "a")) renvoie un vecteur associant chaque chaîne à son nombre d'occurrences :

a b c
4 2 1

2.4 Listes

S'il est bien un concept singulier en R, c'est celui de liste. Autrement dit, si vous avez quelques problèmes avec les listes, veuillez lire cette section jusqu'au bout. Il s'agit d'une collection d'objets, pas nécessairement de mêmes classes. On peut en construire avec la fonction list() :

>
>

>
L <- list(1, 2, "ahah", c(5, 6, 7))
class(L)
[1] "list"
length(L)
[1] 4

Chaque objet peut être appelé selon sa position dans la liste :

>



L[[3]] ; L[[4]]
[[1]]
[1] "ahah"

[[1]]
[1] 5 6 7

Notons que L[3] et L[4] fonctionnent également, mais pas si l'on veut appeler un sous-élément (ici, le second élément du quatrième objet) :

>

>

L[[4]][[2]]
[1] 6
L[4][2]
<NA>
NULL

L[2] <- 43 affecte une nouvelle valeur au deuxième élément
L[] <- 17 affecte une même valeur à tous les éléments de la liste
L[length(L) +1] <- 24 ajoute une valeur en fin de liste
L[2:3] ou L[c(1, 3, 5)] sélectionne des éléments selon la séquence ou le vecteur

>






L <- list("a", "b", "c", "d", "e") ; L[c(4,3,1)]
[[1]]
[1] "d"

[[2]]
[1] "c"

[[3]]
[1] "a"

Si le rang de la nouvelle valeur est plus élevé que la longueur de la liste, des valeurs nulles intermédiaires sont créées :

>
>
>









maliste <- list(5, 6)
maliste[4] <- 43
maliste
[[1]]
[1] 5

[[2]]
[1] 6

[[3]]
NULL

[[4]]
[1] 43

C'est ce même NULL qui permet d'enlever un élément :

>







maliste[1] <- NULL ; maliste
[[1]]
[1] 6

[[2]]
NULL

[[3]]
[1] 43

Pour coller deux listes, utiliser la fonction c() (voir chapitre suivant) :

>











liste1 <- list(4, 3)
liste2 <- list("d", "c")
nv <- c(liste1, liste2) ; nv
[[1]]
[1] 4

[[2]]
[1] 3

[[3]]
[1] "d"

[[4]]
[1] "c"

Nommer les éléments

Il existe également un type de liste où chaque élément est nommé. Il est possible d'appeler un de ces éléments par leur nom :

>
>

>



L <- list("a" =1, "b" =2, "c" ="ahah", "d" =c(1,2,3))
L[["c"]]
[1] "ahah"
L["d"] ; L$d ; L$d[2]
$d
[1] 5 6 7

[1] 5 6 7
[1] 6

Il est possible de nommer une liste après coup avec names() :

>
>
>












carres <- list(1, 4, 9, 16, 25)
names(carres) <- c("1^2", "2^2", "3^2", "4^2", "5^2")
carres
$`1^2`
[1] 1

$`2^2`
[1] 4

$`3^2`
[1] 9

$`4^2`
[1] 16

$`5^2`
[1] 25

Note : les `guillemets inversés` apparaissent et doivent être utilisés lorsqu'un nom de colonne n'est pas conforme à la nomenclature des noms de variable.

Délister une liste

Certaines fonctions renvoient des listes, comme celles qui découpent une chaîne par une sous-chaîne :

>
>
>


ch <- "Les sanglots longs des violons"
lst <- strsplit(ch, " ")
lst ; class(lst) ; length(lst)
[1] "Les"      "sanglots" "longs"    "des"      "violons"

[1] "list"
[1] 1

Cette liste (indiquée comme telle) ne possèdant qu'un élément ; chaque mot ne peut donc être appelé selon un quelconque rang dans la liste.

>
lst[[2]]
Error in lst[[2]] : indice hors limites

Il y a peut-être une raison à cela, mais elle ne tombe pas sous le sens. Pour obtenir une collection manipulable de chaînes issues d'une telle découpe, il faut traiter la «liste» par la fonction unlist() :

>
>

unl <- unlist(lst)
unl ; unl[[2]]
[1] "Les"      "sanglots" "longs"    "des"      "violons"
[1] "sanglots"

Le résultat obtenu est un vecteur, les collections sont éclatées, et une seule chaîne transforme tous les éléments en chaînes :

>
>
>
liste <- list(9, 8, "k", list(7, 6))
vect <- unlist(liste)
vect
[1] "9" "8" "k" "7" "6"

3. Vecteurs et distributions

3.1 Vecteurs

c() «combine» fabrique une variable «vecteur», ensemble ordonné d'éléments de même classe. Le [1] (et non [0] comme dans la majorité des langages informatiques) de la réponse indique que la valeur suivante est la première d'une série : pour les longs vecteurs dont les valeurs sont listées sur plusieurs lignes, l'index de la valeur suivante est répété à chaque nouvelle ligne.

>

>



>
a <- c(1, 5, 4, 6, 2, 1, 3, 4, 5, 5) ; a
[1] 1 5 4 6 2 1 3 4 5 5
class(a) ; is(a) ; is.vector(a)
[1] "numeric"
[1] "numeric" "vector"
[1] TRUE
length(a)
[1] 10

class() et is() renvoient des informations sur une variable
is.vector(var) retourne TRUE si var est un vecteur, FALSE sinon

length(a) renvoie la longueur du vecteur, à savoir le nombre d'éléments qu'il contient

+ sert à additionner les éléments terme à terme de deux vecteurs) :

>
>
vec1 <- c(1, 2, 3) ; vec2 <- c(7, 8, 9)
print(vec1 + vec2)
[1]  8 10 12

c() permet également de prolonger une vecteur par un autre vecteur ou d'autres valeurs

>
>
vec1 <- c(1, 2, 3) ; vec2 <- c(7, 8, 9)
vec <- c(vec1, 5, vec2) ; vec
[1] 1 2 3 5 7 8 9

Attention! Dans le cas d'un vecteur contenant au moins une chaîne de caractères, tout nombre est transformé en chaîne :

>
>
a <- c(1, 4, "3", 2, 5)
a ; class(a)
[1] "1"  "4"  "3"  "2"  "5"
[1] "character"

Voyez scan() pour la saisie de valeurs numériques dans un vecteur.

Les opérations sur des vecteurs sont réalisées sur chacun de leurs éléments :

>


>
n <- c(10, 100, 1000) ; n + 5 ; n * 3
[1]   15  105 1005
[1]   30  300 3000
ch <- c("a", "b", "c", "d") ; paste(ch, "bis")
[1] "a bis" "b bis" "c bis" "d bis"

a[3] désigne le troisième élément du vecteur a, qui contient dans l'exemple plus haut le nombre 4
a[3:5] renvoie un vecteur formé des valeurs des positions 3 à 5 (comprise) du vecteur a
a[c(2, 3, 5)] renvoie un vecteur fait des deuxième, troisième et cinquième valeurs du vecteurs a

a[-3] retourne tout le vecteur a diminué de son troisième élément. Cette expression ne modifie pas le vecteur lui-même, sauf dans l'expression a <- a[-3]

a[c(-2, -3, -5)] ou a[-c(2, 3, 5)] retourne le vecteur a diminué de ses deuxième, troisième et cinquième éléments.

which() retourne les index des éléments d'un vecteur contenant une valeur particulière :

>
vec =c(1, 3, 5, 4, 3, 2) ; which(vec ==3)
[1] 2 5

3.2 Génération de vecteurs

letters et LETTERS sont deux vecteurs tout faits comprenant les 26 lettres minuscules et majuscules non accentuées.

letters[5:10] renvoie [1] "e" "f" "g" "h" "i" "j"

Il est possible de générer une séquence de nombre de x à y (inclus) avec l'expression x:y :

>
var <- 13:19 ; var
[1]  13 14 15 16 17 18 19

seq(debut, fin, by =pas) retourne un vecteur rassemblant les nombres entre debut et fin (avec un éventuel pas, qui peut être négatif) :

>

>

>

>
seq(-4, 3)
[1] -4 -3 -2 -1  0  1  2  3
seq(-4, 3, 0.5)
[1] -4.0 -3.5 -3.0 -2.5 -2.0 -1.5 -1.0 -0.5  0.0  0.5  1.0  1.5  2.0  2.5  3.0
seq(4, -3, -1)
[1]  4  3  2  1  0 -1 -2 -3
seq(4)
[1]  1 2 3 4

Notes

rep(qqch, n) répète n fois un vecteur :

>
rep(c(1,2,3,4,5), 3)
[1] 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5

each permet de répéter chaque élément un à un :

>
rep(c(1,2,3,4,5), each=3)
[1] 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5

sample(vect, n) retourne un vecteur de n valeurs au hasard choisies dans le vecteur vect (tirage sans remise : n ne peut dépasser la longueur du vecteur) :

>
sample(1:6, 3)
[1] 5 1 2

sample(vect, n, replace=TRUE) permet un tirage pseudo-aléatoire avec remise et donc un nombre plus grand que la longueur du vecteur (rep=T est un équivalent) :

>
sample(c("P", "F"), 5, rep=T)
[1] "F" "P" "P" "F" "P"

Note : les deux réponses ci-dessus sont susceptibles d'être différentes à chaque «tirage».

3.3 Modifications (d'éléments) de vecteur

a[3] <- 43 affecte une valeur au troisième élément d'un vecteur comprenant au moins 3 éléments
a[] <- 43 affecte une même valeur à tous les éléments d'un vecteur existant
a[3:5] <- c(3,5,8) permet un remplacement d'une série de valeur par une autre, à condition que la séquence 3:5 soit de même longueur que le vecteur qui la remplace
a[c()] <- c() remplace quelques valeurs désignées selon leur rang du vecteur a par un même nombre de valeurs contenues dans un autre vecteur :

>
>
a <- c(1, 2, 3, 4, 5, 6, 7, 8, 9)
a[c(2,4,7)] <- c("x", "y", "z") ; a
[1] "1" "x" "3" "y" "5" "6" "z" "8" "9"

Il est possible de rechercher et modifier une valeur à plusieurs endroits d'un vecteur :

>
>
>
nbr <- c(1, 5, 4, 6, 2, 1, 4, 2, 1)
nbr[nbr ==1] <- 43
nbr
[1] 43  5  4  6  2 43  4  2 43

… dans le vecteur nbr, chaque élément (symbolisé à l'intérieur des crochets par nbr) égal à 1 doit à présent valoir 43

La condition ne se limite pas à l'égalité, mais peut utiliser toute sorte de conditions logiques (> < !=…). Pour agir sur les nombres pairs :

>
>
vec <- c(1,2,3,4,5,6,7,8,9,10,11)
vec[vec %% 2 ==0] <- 43 ; vec
[1]  1 43  3 43  5 43  7 43  9 43 11

Il est également possible de filtrer conditionnellement un vecteur, en ne gardant ici que les nombres impairs :

>
>
vec <- c(2,5,9,4,8,6,11,1,10,7,3)
vec <- vec[vec %% 2 ==1] ; vec
[1]  5  9 11  1  7  3

%in% teste l'appartenance d'un élément dans un vecteur :

>
3 %in% c(1, 3, 4, 8, 9)
[1] TRUE

En combinant condition et appartenance, il est possible de remplacer plusieurs éléments par une même valeur (en cas de vecteur de chaînes, les chaînes entières sont concernées – contrairement à un remplacement dans un texte par gsub() :

>
>
>
valrech <- c("a","b","c") # vecteur de valeurs à chercher
vec <- c("b","ad","ab","a","e","cc","c") # vecteur sur lequel on travaille
vec[vec %in% valrech] <- "oui" ; vec
[1] "oui" "ad"  "ab"  "oui" "e"   "cc"  "oui"

Opérations sur un vecteur

Un vecteur numérique peut être une distribution.

NA («not available») est une valeur qui rend le résultat de tout calcul NA.

sum() retourne la somme des éléments d'un vecteur numérique.

Il est possible d'ajouter (ou de soustraire) un même nombre à l'ensemble des éléments d'un vecteur :

>
>
suite <- c(1, 4, 9, 16)
suite +1
[1] 2 5 10 17

Les fonctions unaires s'appliquent à chaque élément d'un vecteur :

>
>

>
coll <- c(10, 40, 37, 2, 53)
racine <- sqrt(coll) ; racine
[1] 3.162278 6.324555 6.082763 1.414214 7.280110
round(racine, 2)
[1] 3.16 6.32 6.08 1.41 7.28

Il est possible de multiplier (ou de diviser) par un même nombre tous les éléments du vecteur :

>
>
suite <- c(1, 4, 9, 16)
suite *3
[1] 3 12 27 48

Il est possible d'appliquer une fonction à chaque élément d'un vecteur :

>
>
carre <- function(x) { x^2 }
vect <- c(1, 2, 3, 4, 5, 6) ; carre(vect)
[1]  1  4  9 16 25 36

sort(vect) trie les valeurs du vecteur vect :

>
sort(c(5, 0, 6, 4, 8, 3, 2, 9, 1, 7))
[1] 0 1 2 3 4 5 6 7 8 9

Il est possible de préciser decreasing=T et na.last=T ou F. En cas de NA dans le vecteur, omettre na.last élimine les valeurs non attribuées :

>
sort(c(1:5, NA), decreasing=T)
[1] 0 1 2 3 4 5 6 7 8 9

Opérations sur les vecteurs

Rappel : NA («not available») est une valeur qui rend le résultat de tout calcul NA.

min(v1) donne la valeur minimale d'un vecteur
min(v1, v2) donne la valeur minimale parmi deux (ou plusieurs) vecteurs

max(v1) donne la valeur maximale d'un vecteur
max(v1, v2) donne la valeur maximale parmi deux (ou plusieurs) vecteurs

Il est possible d'additionner, multiplier… les vecteurs numériques (de même longueur) entre eux, les opérations affectant les éléments de même rang (v1 %*% v2 est la somme des produits terme à terme) :

>
>


v1 <- c(1, 4, 9, 16) ; v2 <- c(1, -1, 1, -1)
v1 + v2 ; v1 * v2 ; v1 %*% v2
[1]  2  3 10 15
[1]  1 -4  9 -16
     [,1]
[1,]  -10

%in% teste la présence de chaque élément du premier vecteur dans le second (par chaînes entières si variables «caractères») :

>
c(1, 5, 9, 15) %in% c(2, 5, 15, 37, 89)
[1] FALSE  TRUE FALSE  TRUE

< teste la relation de chaque élément du premier vecteur avec l'ensemble des éléments du second (il suffit pour chaque élément du premier de trouver un élément du second satisfaisant à la condition) :

>
c(1,3,15,6,9) < c(2,5,6,7,8)
[1]  TRUE  TRUE FALSE  TRUE FALSE

all() impose la globalité de la réussite du test pour l'ensemble du premier vecteur :

>
all(c(1,3,15,6,9) < c(2,5,6,7,8))
[1]  FALSE

paste(v1, v2, sep="-") assemble terme à terme les éléments de deux vecteurs, il en résulte toujours un vecteur de chaînes.

3.4 Facteurs

La variable de type factor ressemble aux vecteurs, mais permet de stocker de façon économique des données répétitives :

>
>



>


>
vec <- c("Femme", "Homme", "Homme", "Femme", "Femme"")
fac <- factor(vec) ; print(fact) ; class(fact)
[1] Femme Homme Homme Femme Femme
Levels: Femme Homme
[1] "factor"
is(fac)
[1] "factor"              "integer"             "oldClass"
[4] "numeric"             "vector"              "data.frameRowLabels"
is.factor() ; str(fac)
TRUE
Factor w/ 2 levels "Femme","Homme": 1 2 2 1 1

En interne, les données sont codées c("Femme", "Homme") (vecteur des «levels») et c(1, 2, 2, 1, 1), vecteur de 1 et 2 désignant respectivement Femme et Homme. Cela a surtout un intérêt pour les vecteurs comportant des données répétées (variables catégorielles), peu intéressante pour les noms et les rues d'un carnet d'adresses.

print(fact[3]) permet d'accéder au troisième rang de la variable factor
fact[3] <- "Femme" permet de modifier le troisième rang de la variable (la nouvelle doit appartenir à une des catégories)

Il est possible de prévoir une catégorie supplémentaire lors de la constitution de la variablefactor :

fact <- factor(c("Femme", "Homme", "Homme", "Femme", "Femme"), levels = c("Femme", "Homme", "Queer"))

Mais il est également possible de l'ajouter par la suite

levels(fact) <- c(levels(fact), "Queer")

Lors de la constitution d'une table de données, les vecteurs sont par défaut transformés en facteurs.

3.5 Distribution

Tout vecteur de nombres peut être considéré comme une distribution univariée. Il existe des fonctions et graphiques tout faits pour traiter de ce genre de distributions. Pour ces fonctions, préciser na.rm=TRUE («remove non-available values») permet de ne pas prendre en compte les éventuelles valeurs NA qui rendrait la réponse NA.

mean() retourne la moyenne des éléments d'un vecteur (leur somme divisée par leur nombre)
median() retourne la médiane des éléments d'un vecteur (mis en ordre, il s'agit de la valeur du milieu en cas de longueur paire de vecteur, sinon de la moyenne des deux valeurs centrales)

quantile() donne les quartiles d'une distribution (la médiane et les quartiles sont ici interpolés) :

>
dist <- c(1, 6, 5, 3, 4, 6) ; quantile(dist)
0%  25%  50%  75% 100%
1.00 3.25 4.50 5.75 6.00

summary() retourne un vecteur de six éléments : le minimum, le premier quartile, la médiane, la moyenne, le troisième quartile et le maximum. summary(vect)[2] retourne le premier quartile.

var() retourne la variance de la distribution (la variance est une mesure de dispersion d'une distribution ; il s'agit de la somme des différences au carré de chaque valeur à la moyenne, divisée par le nombre d'observations diminué d'1). Pour la variance "n", multiplier par (n-1)/n.

sd() retourne l'écart-type (standard deviation) d'une distribution représentée par un vecteur numérique (l'écart-type équivaut à la racine carrée de la variance). Pour l'écart-type "n", multiplier par sqrt((n-1)/n).

crossprod(v1, v2) retourne une matrice de 1×1 composé de la somme des produits terme à terme de deux vecteurs de longueur égale. v1 %*% v2 retourne le même résultat. Pour le résultat en nombre : (v1 %*% v2)[1][1]

tcrossprod(v1, v2) multiplie le vecteur v1 par chaque terme de v2 , fabriquant une matrice de length(v2) colonnes de longeur length(v1) (v1 et v2 peuvent être de longueurs différentes).

Un vecteur pouvant représenter un tableau de contingence d'une seule rangée, il est possible d'y appliquer le test du χ² (khi-deux) :

chisq.test(vecteur, params) - Attention : admet des petits tableaux de contingence (n =25) sans toujours prévenir de la nullité du test.

Il est possible de visualiser des distributions avec plot() et ggplot().

4. Matrices

Les matrices sont des tableaux à deux dimensions. Elle sont importantes dans les distributions bivariées, ou les enquêtes individus/variables. Il est possible de transformer une matrice en table de données.

matrix() construit une matrice (la première valeur est une variable ou un vecteur de données, la seconde le nombre de rangées (lignes) et la troisième le nombre de colonnes. Le remplissage se fait verticalement, colonne après colonne :

>
>

vect <- c(1, 2, 3, 4, 5, 6)
m <- matrix(vect, 2, 3) ; m
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6

rbind() construit une matrice en additionnant des lignes (rangées) :

>

rbind(c(1,3,5), c(2,4,6))
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6

cbind() construit une matrice en additionnant des colonnes :

>

cbind(c(1,2), c(3,4), c(5,6))
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6

rbind() et cbind() permettent d'ajouter une ligne ou une colonne à une matrice existante (en respectant les dimensions)

length() retourne le nombre d'éléments d'une matrice.
nrow() et ncol() retournent respectivement le nombre de rangées et de colonnes.

L'accès à une donnée se fait au moyen de ses coordonnées [ligne,colonne] :

>
m[1,2]
[1] 3

Il est possible de sélectionner toute une rangée ou toute une colonne sous forme de vecteur :

>

>
m[2,]
[1] 2 4 6
m[,2]
[1] 3 4

Il est possible de sélectionner une sous-matrice en utilisant des séquences, ici les rangs 1 à 2 et les colonnes de 2 à 3 :

>


m[1:2,2:3]
     [,1] [,2]
[1,]    3    5
[2,]    4    6

Si la sélection ne porte que sur une ligne ou une colonne, le résultat retourné est converti en vecteur :

>
v <- m[1:2, 3] ; v ; is(v)
[1] 5  6
[1] "numeric" "vector"

drop=FALSE permet d'éviter cette conversion pour garder une matrice d'une ligne ou d'une colonne :

>


m[1:2, 3, drop =F]
     [,1]
[1,]    5
[2,]    6

View(matrice) permet de visualiser une matrice dans un tableau graphique, print(matrice) l'affiche dans une console.

Initialisation de matrices

Pour fabriquer une matrice uniforme, soit une seule valeur partout, il suffit de l'indiquer en première position :

>


m <- matrix(0, 2, 3)
     [,1] [,2] [,3]
[1,]    0    0    0
[2,]    0    0    0

Pour initialiser une matrice de chaînes :

>


matrix("", 2, 3)
     [,1] [,2] [,3]
[1,]   ""   ""   ""
[2,]   ""   ""   ""

Il est possible de définir une matrice de nombres impairs à partir de la séquence 0:5 (vecteur des nombres de 0 à 5 inclus) :

>


matrix(0:5 *2 +1, 2, 3)
     [,1] [,2] [,3]
[1,]    1    5    9
[2,]    3    7   11

Opérations sur une matrice

Comme les vecteurs, chaque terme d'une matrice peut être multiplié (ou divisé, ou soumis à un exposant).

>


matrix (0:5, 2, 3) *2
     [,1] [,2] [,3]
[1,]    0    4    8
[2,]    2    6   10

-matrice change le signe de tous les termes
1 /matrice remplace chaque terme par son inverse (Inf ou -Inf si terme négatif)
sqrt(matrice) racine carrée de chacun des termes (NaN en cas de terme négatif)
exp(matrice) remplace chaque terme en exp(x)
etc.

aperm(matrice) intervertit lignes et colonnes :

>



>


m <- matrix (0:5, 2, 3) ; m
     [,1] [,2] [,3]
[1,]    0    2    4
[2,]    1    3    5
m <- aperm(m) ; m
     [,1] [,2]
[1,]    0    1
[2,]    2    3
[3,]    4    5

Une matrice pouvant représenter un tableau de contingence, il est possible d'y appliquer des tests statistiques :

chisq.test(matrice, params) réalise le test du χ² (khi-deux)
fisher.test(matrice, params) réalise le test exact de Fisher

Matrices carrées

det(m) retourne le déterminant d'une matrice
solve(m) retourne une matrice inverse (sous certaines conditions)
p =eigen(m) calcule les valeurs propres (p$values) et les vecteurs propres p$vectors

Opérations sur deux matrices

Deux matrices de mêmes dimensions peuvent additionner et soustraire leurs éléments terme à terme.

>

matrix (0:5, 2, 3) + matrix(10, 2, 3)
     [,1] [,2] [,3]
[1,]   10   12   14
[2,]   11   13   15

Les multiplication * et division / de deux matrices correspondent à la multiplication et à la division de leurs éléments terme à terme :

>



>



>


m <- matrix (0:5, 2, 3) ; print (m)
     [,1] [,2] [,3]
[1,]    0    2    4
[2,]    1    3    5
n <- matrix (0:5*2+1, 2, 3) ; print (n)
     [,1] [,2] [,3]
[1,]    1    5    9
[2,]    3    7   11
m *n
     [,1] [,2] [,3]
[1,]    0   10   36
[2,]    3   21   55

m **n soumet les éléments de la première matrice aux exposants contenus dans la seconde.

La vraie multiplication de matrices nécessite que le nombre de colonnes et le nombre de lignes de l'une soient les inverses de l'autre. Utiliser %*% et %/% dans ce cas seulement :

>



>




>


m <- matrix (0:5, 2, 3) ; print (m)
     [,1] [,2] [,3]
[1,]    0    2    4
[2,]    1    3    5
n <- matrix (0:5*2+1, 3, 2) ; print (n)
     [,1] [,2]
[1,]    1    7
[2,]    3    9
[3,]    5   11
m %*%n
     [,1] [,2]
[1,]   26   62
[2,]   35   89

Pour rappel,

5. Tables de données

Une table de données est un tableau de valeurs organisées en vue d'être traitées (lues, modifiées, filtrées, regroupées, additionnées, etc.). Une table est constitué de rangées représentant des enregistrements (individus, objets, observations…) et colonnes (variables contenant principalement des nombres et des chaînes de caractères).

Une base de données peut contenir plusieurs tables en relation les unes avec les autres. Bien qu'une base de données puisse n'être constituée que d'une seule table (typiquement un carnet d'adresse), cette page n'utilise jamais le mot «base» pour «table».

R a prévu quelques variables rendant disponibles des tables de données toutes faites sur lesquels il est possible de tester les différentes fonctions qui s'y appliquent :

Il est possible d'ouvrir ou d'importer un fichier contenant une table de données, mais il sera question dans ce début de chapitre de la façon de produire ce genre de table, en transformant, avec as.data.frame(), une matrice en table de données :

V1V2V3V4
1Richard1791979.06.12M
2Philippe1831981.04.23C
3Louis1771984.11.12M
>
>
>
>
>
vect <- c("Richard", "Philippe", "Louis", 179, 183, 177,
     "1979.06.12", "1981.04.23", "1984.11.12", "M", "C", "M")
mat <- matrix(vect, 3, 4)  # transforme le vecteur en  matrice 3 rangs / 4 colonnes
df <- as.data.frame(mat)   # transforme la matrice en table de données
View(df)

Le vecteur initial contenant au moins une chaîne, toutes les valeurs le composant sont également des chaînes, même si cela ne se voit pas dans le tableau produit par View() ou print().

data.frame() permet d'assembler des vecteurs de même longueur en table de données :

nomtaillenaissanceé_c
RiriRichard1791979.06.12M
FifiPhilippe1831981.04.23C
LoulouLouis1771984.11.12M
>
>
>
>
>
>
>
nom <- c("Richard", "Philippe", "Louis")
taille <- c(179, 183, 177)
naissance <- c("1979.06.12", "1981.04.23", "1984.11.12")
é_c <- c("M", "C", "M")
df <- data.frame(nom, taille, naissance, é_c, stringsAsFactors =FALSE)
rownames(df) <- c("Riri","Fifi","Loulou")
print(df)

Propriétés du tableau

class(df) renvoie "data.frame" ; is(df) est plus complet
dim(df) renvoie un vecteur contenant les dimensions de la table : 3 (observations), 4 (variables)

attributes(df) renvoie les noms de variables, la classe et le nom des colonnes : $names, $class et $row_names (sans guillemets)

str(df) renvoie la structure d'un objet, complexe pour une table de données :

'data.frame':	3 obs. of  4 variables:
 $ nom      : chr  "Richard" "Philippe" "Louis"
 $ taille   : num  179 183 177
 $ naissance: chr  "1979.06.12" "1981.04.23" "1984.11.12"
 $ é_c      : chr  "M" "C" "M"

Sans stringsAsFactors =FALSE, la dernière ligne serait :

 $ é_c      : Factor w/ 2 levels "C","M": 2 1 2

Rangées

nrow(df) renvoie le nombre d'observations : 3
rownames(df) ou row.names(df) renvoie le nom des rangées ou permet de spécifier les noms d'observation ("1", "2", "3"… par défaut)

>
rownames(df) <- c("N01", "N02", "N03") ; View(df)

Colonnes

df$couvert <- c("cuiller", "couteau", "fourchette") ajoute une colonne à une table de données
df$couvert <- NULL supprime la colonne désignée par son nom.

ncol(df) ou length(df) renvoie le nombre de variables (colonnes) : 4
names(df) ou colnames(df) renvoie les noms de variables (de colonnes) : "nom" "taille" "naissance" "é_c", ou permet de les assigner (pour éviter les noms V1, V2, V3… par défaut) :

>
>
colnames(df) <- c("nom","taille","naissance","é_c")
View(df)

Extraire des données

Vous pouvez expérimenter dans R, Rcmdr ou Rstudio les commandes ci-dessous si vous y collez-copiez le bloc de code qui suit data.frame() (sans les invites ">").

Sélection de colonne(s) :

df["nom"] ou df[1] renvoie une table constituée des valeurs de la colonne couv ou de la colonne n° 2
df[2:4] renvoie une table constitué des colonnes contiguës de 2 à 4
df[c("nom","é_c")] et df[c(1,4)] renvoient une table de plusieurs colonnes choisies par leurs noms ou leurs rangs

df$taille ou df[, 2] renvoie un vecteur constitué des valeurs de la colonne taille ou de la colonne n° 2
df[, "taille", drop=F] ou df[, n, drop=F] retourne une table (drop=F) des valeurs de la variable couv ou de la colonne n

Sélection de rangée(s), virgule à droite indispensable :

df[1,] df["Riri",] renvoie une table d'une observation sélectionnée par son rang ou son nom
df[2:3,] renvoie une table de plusieurs lignes contiguës
df[c(1,3),] et df[c("Riri","3"),] renvoient une table de plusieurs lignes choisies par n° ou nom de ligne

Sélection d'observation(s), coordonnées lignes/colonnes :

df$naissance[3] retourne la valeur de la 3° observation de la colonne couv (vecteur d'un seul élément)
df$naissance["Riri"] l'expression n'accepte pas la désignation d'une rangée par son nom (NA)

df[3, 4] et df["3", "é_c"] retourne la valeur de la 3° observation de la quatrième colonne é_c (vecteur d'un seul élément)

df[c(2, 3), c("taille", "naissance")] retourne une table contenant les valeurs des colonnes taille et naissance des 2° et 3° observations

df[1:2, "taille"] ou df$taille[c(1, 3)] renvoie un vecteur des observations sélectionnées de la colonne "taille"
df[c(1:2),"taille", drop =FALSE] renvoie une table des 2° et 3° observations de la colonne "mot"
df$taille[c(1, 3), drop=F] ne permet pas d'obtenir le résultat de la sélection sous forme de table

subset() extrait sous forme de table des observations selon des conditions (elles peuvent être composées avec tout opérateur logique :

subset(df, é_c =="M")

           nom taille  naissance é_c
Riri   Richard    179 1979.06.12   M
Loulou   Louis    177 1984.11.12   M

Lors du chargement d'une table de données ou de sa définition ne passant pas par des vecteurs, R ne connaît pas le nom des variables des colonnes. attach() le permet :

>
>
>
>
>
df <- as.data.frame(matrix(c("Anne", "Julie", "Michel",168, 173, 170), 3, 2))
attach(df)
print(V1)
detach(df)
print(V1)

detach(df) est censé permettre de ne plus avoir accès aux variables (fonctionne dans R console, mais pas dans Rstudio).

with(df, commande()) permet également des commandes ayant un accès aux variables :

df <- as.data.frame(matrix(c("Anne", "Julie", "Michel",168, 173, 170), 3, 2))
with(df, print(V1))

…mais pour écrire dans la table de données, il faut spécifier une variable :

>
>
>



df <- data.frame(n=c("Anne", "Julie", "Michel"), t=c(168, 173, 170))
df$diff <-with(df, t -mean(t))
df
       n   t       diff
1   Anne 168 -2.3333333
2  Julie 173  2.6666667
3 Michel 170 -0.3333333

within(df, { diff <- t -mean(t) } ) est une variante.

Ordonner une table de données

order(table$variable),] permet le tri d'un table selon une variable :

>
>
>
>
pren <- c("Anne", "Julie", "Michel")
taille <- c(168, 173, 170)
df <- data.frame(pren, taille, stringsAsFactors =F)
nv <- df[order(df$taille),] ; print(nv)

Il est possible d'ajouter des conditions de tri (sur d'autres variables) et une commande pour un tri descendant :

>
>
>
>
pren <- c("Anne", "Julie", "Michel")
taille <- c(168, 170, 170)
df <- data.frame(pren, taille, stringsAsFactors =F)
nv <- df[order(df$taille, df$pren, decreasing=T),] ; print(nv)

Joindre des tables de données

rbind(df1, df2) joint deux tables contenant les mêmes noms de colonnes / variables. Le r de rbind() vient de row, puisqu'il s'agit d'ajouter des rangées

>
>
>
>
>




df1 <- data.frame (x =c(1,2,3), y =c("a","b","c"))
rownames(df1) <-c("A","D","N")
df2 <- data.frame (x =c(4, 5), y =c("d", "e"))
rownames(df2) <-c("X", "Z")
rbind (df1, df2)
   x y
A  1 a
D  2 b
N  3 c
X  4 d
Z  5 e

Il existe une technique permettant de nourrir une base de données, par exemple dans une boucle. On part alors d'une table de données vide mais dont les colonnes ont été prévues, à laquelle on ajoute une ou plusieurs rangée·s de données :

df <- data.frame(nom=character(), prenom=character(), age=numeric())
df <- rbind(df, data.frame(nom="Rigby", prenom=("Eleanor"), age=75))

Lors de la jointure de deux bases de données, il se pourrait que deux noms de rangée soient égaux. Par sécurité, le second de deux noms de rangée identiques est modifié pour lever l'ambiguïté.

>
>
>
>
>




df1 <- data.frame (x =c(1,2,3), y=c("a","b","c"))
rownames(df1) <-c("A","B","C")
df2 <- data.frame (x =c(4,5), y=c("d","e"))
rownames(df2) <-c("A","B")
rbind (df1, df2)
   x y
A  1 a
B  2 b
C  3 c
A1 4 d
B1 5 e

Il est possible d'ajouter une rangée de nombres ou de chaînes de même valeur :

>



rbind (df1, "a")
  x y z w
A 1 a f k
B 2 b g z
C 3 c h j
4 a a a a

cbind(df1, df2) joint les colonnes de bf2 à celle de bf1. Les tables doivent avoir le même nombre de rangées/enregistrements. Attention, la commande ne vérifie pas le nom des colonnes, ce qui peut poser des problèmes.

>
>
>


df1 <-data.frame(x=c(1,2,3), y=c("a","b","c"))
df2 <-data.frame(z=c(4,5,6), y=c("d","e","f"))
cbind(df1, df2)
  x y z t
1 1 a 4 d
2 2 b 5 e
3 3 c 6 f

Il est possible d'ajouter une colonne de constante ou une formule :

>
>
>


df1 <-data.frame(x =c(1,2,3), y =c("a","b","c"))
df2 <-data.frame(z =c(4,5,6), y =c("d","e","f"))
cbind (df1, df2, a =length(df1))
  x y z t a
1 1 a 4 d 2
2 2 b 5 e 2
3 3 c 6 f 2

merge() assemble deux tables qui possède (au moins) une colonne commune (ordre pour cet l'exemple) :

>
>
>
>
>
>
>
>
>


ordre <- c(1, 2, 3)
pren <- c("Anne", "Julie", "Michel")
nom <- c("Cuiller", "Couteau", "Fourchette")
gens <- data.frame(ordre, pren, nom)
film <- c("Providence","Casanova","Sacré Graal")
livre <- c("L'étranger","L'immoraliste","Le vagabond")
culte <- data.frame(ordre, film, livre)
tout <- merge(gens, culte, by ="ordre")
print(tout)
  ordre   pren        nom        film         livre
1     1   Anne    Cuiller  Providence    L'étranger
2     2  Julie    Couteau    Casanova L'immoraliste
3     3 Michel Fourchette Sacré Graal   Le vagabond

Note : si la variable commune de l'un n'est pas complète, le résultat sera tronqué.

Croisement de variables

xtabs() permet la sommation d'une variable selon une autre :

>
>
>
>
>
>


sexe=c("G", "G", "G", "F", "F", "F", "G", "F", "F", "G")
note=c(15, 12, 11, 12, 17, 11, 13, 15, 10, 9)
df <- data.frame(sexe, note)
somme <- xtabs(get("note") ~ get("sexe"), data =df)
names(dimnames(somme)) <- "Somme des résultats par sexe"
print(somme)
Somme des résultats par sexe
 F  G
65 60

table() produit un tableau de contingences à partir du croisement de deux variables :

>
>
>
>


sexe <- c("F","G","F","G","G","F","F","G","F","F")
sang <- c("A","B","A","A","O","O","O","A","O","A")
df <- cbind.data.frame(sexe, sang)
table(df$sexe, df$sang)
  A B O
F 3 0 3
G 2 1 1

À suivre…

6. Entrées et sorties

6.1 Clavier et console

Entrées au clavier

readline() permet la saisie d'une chaîne de caractères, s'interrompant avec [Enter] :

>
name <- readline(prompt = "Un nombre de 1 à 10… ")

…mais cela ne fonctionne qu'en mode interactif (R dans une console ou dans Rstudio).

readLines() permet une saisie au clavier en mode script. "stdin" désigne l'entrée standard (la console), n (facultatif) permet de prévoir le nombre de lignes à prévoir avant la saisie de l'ensemble (il ne semble pas possible de savoir comment forcer la saisie avant d'avoir atteint le nombre de lignes indiqué) :

cat("Un nombre de 1 à 10 : ")
n <- as.numeric(readLines("stdin", n=1))
print(switch(n, "un", "deux", "trois", "quatre", "cinq", "six", "sept", "huit", "neuf", "dix"))

scan() permet la saisie de nombres en un vecteur numérique (point décimal, notation scientifique de type 3e-6 et NA sans guillemet sont acceptés, mais erreur pour tout caractère, entouré ou non de guillemets). La séparation entre les nombres est l'espace, il est possible de revenir à la ligne avec un retour-chariot ; la saisie d'une ligne vide interrompt le processus.

>
1:
4:
7:

vect <- scan() ; vect
5 4 3
2 1 5

Read 6 items
[1] 5 4 3 2 1 5

Il est possible de limiter a priori le nombre maximal de ligne (l'interruption par la saisie d'une ligne vide reste valide) :

>
1:
4:

vect <- scan(nlines =2) ; vect
1 2 3
4 5 6
Read 6 items
[1] 1 2 3 4 5 6

Sortie sur la console

print() permet la sortie d'une valeur (nombres, textes, vecteurs ou résultat d'une fonction), avec retour à la ligne. Les chaînes sont entourées de guillemets, et les vecteurs et matrices structurés

>



print(matrix(1:12,3,4))
     [,1] [,2] [,3] [,4]
[1,]    1    4    7   10
[2,]    2    5    8   11
[3,]    3    6    9   12

Pour éventuellement composer des chaînes, utiliser paste() :

>
print(paste("pi vaut", pi))
[1] "pi vaut 3.14159265358979"

cat() est plus spécialisée dans le formatage de la chaîne à sortir, en ignorant toute structure des données (pour récupérer une concaténation dans une variable, utiliser paste()).

>
cat("a", "b", "c", sep="")
abc

cat() n'entoure pas les chaînes de guillemets, et il faut lui préciser le saut de ligne :

>
+





cat(matrix(1:12, 3, 4), unlist(strsplit("les sanglots longs des violons de l'automne", " ")),
  sep ="-", fill =15, labels=c("a:", "b:", "c:"))
a: 1-2-3-4-5-6-
b: 7-8-9-10-11-
c: 12-les-
a: sanglots-
b: longs-des-
c: violons-de-
a: l'automne

Note : contrairement à paste(), cat() assemble les éléments d'un vecteur.

6.2 Fichiers de simple texte

chaine <- scan("nomdufichier.txt", what ="character", sep ="\n") lit un fichier de caractères dont les lignes sont séparées par la fin de ligne UNIX \n

cat() permet d'écrire dans un simple fichier de texte :

cat("les sanglots longs des violons de l'automne", file ="verlaine.txt")

Exemple un peu plus complexe, qui permet un certain formatage de sortie :

vec =c("les", "sanglots", "longs", "des", "violons", "de", "l'automne")
cat(vec, sep=" / ", fill=30, file="ver-lai-ne.txt", append=T)

produit le fichier ver-lai-ne.txt contenant :

les / sanglots / longs /
des / violons / de /
l'automne

append=T permet un ajout à un fichier existant, qui sera sinon écrasé.

Pour la sortie d'une chaîne avec cat(), voir Sortie console

6.3 Tables textes (csv et tsv)

Lecture de fichiers csv et tsv

df <- read.csv("nomdufichier", params ="") ouvre un ficher de texte contenant des données aux conventions csv ("comma separated values", format pas vraiment standardisé). Les données d'une même ligne sont séparées par des virgules, chaque observation (individu) par une fin de ligne (Unix \n ou Windows \r\n). Les chaînes sont entourées de guillemets doubles et le point est le séparateur décimal. La première ligne comprend les titres de colonnes (variables) et chaque ligne commence par un nom de rangée. La variable réceptrice (df) est une table de données (data.frame).

df <- read.csv2("nomdufichier", params ="") offre des variantes par rapport au précédent, plus adaptées aux conventions latines : le séparateur est le point-virgule, pour ne pas interférer avec le séparateur décimal, qui est la virgule.

df <- read.table("nomdufichier", params ="") est plus subtil. Si la première ligne contient une valeur de moins que les autres, elle est interprétée comme titres de colonnes et la première valeurs des autres lignes est considérée comme nom d'observation. Si toutes les lignes ont un nombre égal de valeurs (le séparateur de données est la tabulation \t), la première ligne est considérée comme une observation comme les autres et les noms de colonnes seront V1, V2… Les chaînes sont entourées de guillemets doubles et le séparateur décimal est le point.

Il est possible de modifier ces spécifications des trois dernières commandes en ajoutant (à la place de param ="") :

Il est également possible d'ajouter d'autres précision :

Écriture de fichiers csv et tsv

write…(df, fichier, params) écrit une table de données sous la forme csv, selon diverse modalités : write.csv(), write.csv2() et write.table() suivent les spécifications décrites à la commande read().

write(c(1:12), file="col3.tsv", ncolumns = 3, sep="\t") sauvegarde des données en trois colonnes ; elles sont ici séparées par des tabulations

6.4 Tables binaires (rds et rda)

Table de données

df <- readRDS("monfichier.rds") charge une table de données préalablement sauvegardée avec saveRDS()

saveRDS(objet, file ="monfichier.rds") sauvegarde un objet (chaîne, vecteur ou table de données) dans un format binaire, ensuite mobilisable par readRDS(). Une chaîne sauvegardée produira une table d'une cellule, un vecteur une colonne.

Base de données

vect <- load("bd.rda") lit une base de données de plusieurs tables sauvegardées par save(). Il en résulte un vecteur des noms des tables sauvegardées.

save(df1, df2, df3, "bd.rda") permet la sauvegarde de plusieurs tables de données.

Espace de travail

save.image(file ="espace.RData") sauvegarde l'espace de travail (toutes les variables ouvertes à un moment donné par R)

load("espace.RData") récupère l'espace de travail.

6.5 Importation et exportation

Importer un fichier d'une autre application est souvent plus délicat qu'exporter une base de données vers une autre application, ce qui peut le plus souvent se faire à l'aide d'un fichier .csv (voir supra). Il faut sinon avoir recours à des bibliothèques.

foreign

library(foreign) charge la bibliothèque de fonctions foreign permettant l'importation de plusieurs type de bases de données. L'extension est normalement installée par défaut avec R, sous le nom de paquetage r-cran-foreign pour le système Linux/Debian. Cette bibliothèque permet normalement d'importer une base de données de type .spss (SPSS .sav), .dbf (dBaseII, dBaseIII, dBaseIV et Clipper), .dta (Stata), .arff (Weka), Minitab, S, SAS, Systat

Format .dta de STATA

db =read.dta ("chemin/ma_base.dta")

Format .arff de Weka

db =read.arff ("chemin/ma_base.arff")

Format .sav de SPSS/PSPP (import puis export)

db =read.spss ("chemin/ma_base.sav")
write.foreign(db, "mabase.sav", "mabase.sps", "SPSS")

Format .dbf de dBaseII, III et IV

db =read.dbf ("chemin/ma_base.dbf")

readODS

Pour lire des fichiers ods de Libreoffice calc :

install.packages ("readODS")
library (readODS)
db =read_ods("nomdufichier.ods", col_names =F)

D'autres spécificités :

openxlsx

Pour importer un fichier xlsx Excel, il faut utiliser la bibliothèque openxlsx :

library (openxlsx)
db =read.xlsx ("chemin/votre_feuille.xlsx")

7. Divers

7.1 Système de fichiers

Répertoires

getwd() contient le répertoire courant («working directory»)

setwd("repertoire/sous-repertoire") définit le répertoire courant
setwd("..") permet de remonter au répertoire parent

dir.exists("nom2dossier") renvoie TRUE si le sous-répertoire se trouve dans le répertoire courant
dir.create("nom2dossier") crée un nouveau répertoire
file.exists("nom2dossier") TRUE si existence d'un sous-répertoire dans le répertoire courant
unlink("nom", recursive =TRUE) supprime un répertoire

list.files() liste les fichiers du répertoire courant
list.files("repertoire") liste les fichiers d'un sous-répertoire
list.files(recursive =TRUE) liste tous les fichiers du répertoire et de tous les sous-répertoires
list.files(pattern =".txt") ne liste que les fichiers contenant l'extension txt

Fichiers

file.create("nom2fichier.ext") crée un fichier vide
file.exists("nom") TRUE si existence d'un fichier dans le répertoire courant
unlink() et file.remove("nom2fichier") suppriment un fichier

file.rename(from ="nom1", to ="nom2") renomme un fichier
file.copy(from ="nom1", to ="nom2", overwrite =TRUE) copie un fichier, overwrite =T écrase un éventuel fichier du même nom existant
file.append("nom1", "nom2") ajoute le fichier nom2 à nom1

file.info("nom2fichier")
file.mtime("nom2fichier")
file.size("nom2fichier")

basename("chemin/vers/nom2fichier") renvoie le nom de fichier nom2fichier
dirname("chemin/vers/nom2fichier") renvoie chemin/vers

file.path("repertoire", "sous-rep", "sous-sous-rep", "nom2fichier")

Le package fs fait la même chose (en remplaçant les . des fonctions par des _ , avec une meilleur compatibilité entre OS.

8. Sortie graphique

8.1 plot()

plot(pressure$pressure, params=…) dessine les valeurs de la variable pressure selon leur ordre dans pressure , les valeurs sont représentées par des cercles. Les paramètres principaux sont :

plot(pressure$temperature, pressure$pressure) dessine un graphique avec une relation entre deux variables, la première variable en abscisse, la seconde en ordonnée (les «points» aux coordonnées sont des cercles)

Note : plot(pressure$temperature ~ pressure$pressure) inverse les valeurs sur les axes.

barplot(iris$Petal.length) donne un graphique affichant des barres verticales : les paramètres type et pch de plot ne sont pas valides.

boxplot(iris$Petal.length) graphique «boîte à moustaches», basé sur la médiane (grosse ligne du rectangle), les quartiles (limites du rectangle), les premier et neuvième déciles (limite des lignes), et les valeurs extrêmes sous forme de points (ou autre caractère si pch=n). Les valeurs aberrantes (inférieures de plus de 1,5 fois l'écart interquartile du premier quartile ou supérieures de plus de plus de 1,5 fois l'écart interquartile du troisième quartile) sont notées par des points.

hist(iris$Petal.length, breaks =10) dessine un histogramme, qui regroupe les valeurs d'une variable numérique entre certaines bornes, produisant des planches de hauteur selon le nombre de valeurs regroupées, breaks indique le nombre de planches à produire.

curve(formule, from =deb, to =fin) dessine une courbe selon l'équation formule, de x allant de deb à fin :

curve(cos(pi*x)/x, from = 2, to =10) # sinusoïdale amortie

Ajouts aux graphiques

Ces fonctions graphiques peuvent s'ajouter sur un graphique préalablement réalisé :

lines(pressure$temperature, pressure$pressure) (sur un plot préalable) ajoute une ligne rejoignant les cercles

abline(c, m) trace une droite de pente m passant par le point de coordonnée (0, c) (équation y = m*x +c) :

Cette dernière forme permet de tracer, dans un graphique univarié, une moyenne mean() ou une médiane median() :

versi <- subset(iris, Species =="versicolor")
plot(versi$Petal.Length)
abline(h=mean(versi$Petal.Length), col="magenta")
abline(h=median(versi$Petal.Length), col="blue")

Pour tracer une droite de régression dans un graphique bivarié, il faut utiliser lm() de la bibliothèque stats :

# filtre la variété versicolor
versi <- subset(iris, Species =="versicolor")
# calcul de la régression linéaire
library(stats)
droite <- lm(Petal.Width ~ Petal.Length, data = versi)
coeff <- coefficients(droite)
# équation (sera le titre du graphique) ; "+"[sign(coeff[1])==1] affiche '+' si positif
equation <- paste0("y =", round(coeff[2],2), "x ","+"[sign(coeff[1])==1], round(coeff[1],2))
plot(versi$Petal.Length, versi$Petal.Width, main=equation)
abline(droite, col="magenta")
droite

8.2 ggplot() + geom_…()

Comme R, la bibliothèque ggplot2 contient des exemples de tables de données, comme mpg (234 modèles de voitures). Il est également possible d'utiliser pour les exemples les tables de données toutes faites, par exemple iris et pressure du logiciel R, en mode console ou avec Rstudio.

Il est à noter que la fonction ggplot nécessite toujours un mode d'affichage, sous la forme + geom_…()

Histogrammes

ggplot(iris, aes(x= Sepal.Length)) + geom_bar() réalise un histogramme (une seule variable) à partir de la colonne Sepal.Length de la table de données interne iris. Les valeurs de la colonnes sont rassemblées et le nombre de chaque valeur exprimé sous forme de colonnes (geom_bar()), verticales si x=, horizontales si y=

ggplot(iris, aes(x= Sepal.Length, fill =Species)) + geom_bar() scinde et colorise les colonnes en fonction des trois noms contenus dans la variable Species

Si une barre est partagée par plusieurs espèces, les couleurs se superposent. Pour cliver chaque barre selon les espèces, préciser geom_bar(position = "dodge")

Pour changer les couleurs, il est possible d'ajouter + scale_fill_manual(values=c("#dd0000", "#00cc00", "#0000dd"))

Boîtes à moustaches

ggplot(iris, aes(x =1, y =Petal.Length)) +geom_boxplot() réalise une boîte à moustaches sur une valeur (x =1 assigne une valeur arbitraire à l'axe des x, qui n'a pas de grandeur.

Cela semble plus évident lorsque la variable est ventilée selon une variable facteur :

ggplot(iris, aes(x = Species, y = Sepal.Length)) +geom_boxplot() ventile la variable y en trois distribution selon un facteur discriminant (ici, la variable Species).

ggplot(iris, aes(x = Species, y = Sepal.Length, fill =Species)) + geom_boxplot() attribue une couleur différente pour les trois boîtes à moustaches générées

Graphiques bivariés

ggplot(iris, aes(x= Sepal.Length, y =Petal.Length)) + geom_point() charge la table de données interne iris, assigne les valeurs des abscisses (x) et des ordonnées (y) à deux variables de la table de données, respectivement Sepal.Length et Petal.Length, et dessine un point à chaque coordonnées (x, y).

ggplot(iris, aes(x= Sepal.Length, y =Petal.Length, color=Species)) + geom_point() colore les points selon les espèces. Pour fixer soi-même les couleurs, ajouter

+ scale_color_manual(values=c("#dd0000", "#00bb00", "#0000dd"))

+ geom_…() pour l'affichage

geom_bar() histogramme (univariées uniquement)

geom_point() indique des points pour les distributions bivariées

geom_line() trace une ligne entre les coordonnées d'une distribution bivariée

geom_smooth() affiche une courbe de régression ; geom_smooth(method=lm) pour une droite de régression

geom_col() agrège une variable numérique selon une variable facteur (fill=Species pour colorer les colonnes) :

ggplot(iris, aes( Species, Petal.Length, fill=Species)) + geom_col()

geom_count() l'affichage est pondéré en cas de plusieurs observations aux coordonnées égales (bivariés). Par défaut, la grosseur des points varient selon le nombre ; il est possible de préciser alpha=0.5 (les disques sont plus (0.9) ou moins (0.1) opaques, compatibles avec geom_point())

ggplot(iris, aes(x= Sepal.Length, y =Petal.Length, color =Species, shape =Species)) + geom_point() impose une couleur et une forme de points selon la variable Species d'iris (trois variétés).

ggplot(iris, aes(x = Sepal.Length, fill=Species)) + geom_col(position = "dodge") la colonne représentant x est divisée si plus d'une Species sont représentées à cette valeur.

size =variable ou color =variable permet de pondérer chaque observation (par la taille du point ou par l'intensité de la couleur), ce qui permet la prise en compte d'une troisième variable / troisième dimension :

ggplot(iris, aes(x= Sepal.Length, y =Petal.Length, size =Sepal.Width, color =Species)) + geom_point(alpha=.3)

+ labs() pour les titres et étiquettes

labs(title="", x ="", y="") permet d'ajouter un titre ou de modifier les étiquettes des axes (par défaut, le titre des axes sont le nom des colonnes).

+ xlim() et/ou ylim() pour recadrer le graphique

+ scale_x_discrete() et/ou scale_y_discrete() pour recadrer le graphique

ggsave() pour sauvegarder le graphique

ggsave("nom.png", width=, height=) sauvegarde le dernier diagramme produit. .png pour un nom de fichier compressé sans perte

9. Bibliothèques

La programmation moderne fait appel à des fonctions qui ne sont pas écrites dans l'application principale (R en l'occurrence), mais dans des compléments souvent développés indépendamment, qui ont pour nom «bibliothèques» («library» en anglais) à télécharger sous forme de packages. Par exemple, l'ouverture d'un fichier au format R utilise une fonction interne à l'application, mais l'ouverture d'un fichier d'autres format (DBF, SAV…) se fera par une fonction appartenant à la bibliothèque foreign.

La page cran.r-project.org/web/packages liste plus de 18 000 bibliothèques disponibles (août 2021), avec un lien vers un fichier de présentation.

Installation

Certaines sont automatiquement installées avec R, mais les plus nombreuses doivent être expressément installées. En Linux, l'installation peut parfois être faite, comme pour toute autre application, par son nom de paquetage. Mais si vous disposez d'une connexion Internet, le plus simple est d'utiliser la ligne de commande R, qui télécharge et installe elle-même la bibliothèque. Pour la bibliothèque ggplot2, qui propose des graphiques plus élaborés :

>
install.packages("ggplot2")

En UNIX, Rstudio charge les bibliothèques dans l'espace /home/toto/R pour l'utilisateur toto. Si l'on veut que plusieurs utilisateurs aient accès aux mêmes bibliothèques, il faut lancer R dans une console en mode super-utilisateur (su + mot de passe super-utilisateur, puis saisir R en majuscule). Les bibliothèques seront alors installées dans le répertoire /usr/local/lib/R/site-library/ :

su + mot de passe
super-utilisateur
#
R install.packages("ggplot2")

L'installation n'est à faire qu'une fois par système installé. Notez donc les bibliothèques que vous utilisez pour les retrouver facilement à chaque mise-à-jour majeure de votre système.

Certaines bibliothèques peuvent s'avérer inutiles, entrer en conflit avec d'autres, ou être dépassées par de nouvelles. Pour désinstaller une bibliothèque et libérer un peu de place sur le système :

>
remove.packages("ggplot2")

Dans les systèmes UNIX, le mode super-utilisateur est requis pour désinstaller une bibliothèque qui avait été installée en mode super-utilisateur. Mais n'utilisez jamais ce mode pour le travail quotidien car il produit des fichiers illisibles par les utilisateurs ordinaires.

Utilisation de bibliothèques

Pour utiliser les fonctions d'une bibliothèque installée, à chaque session ou en début de script :

>
library(ggplot2) # les guillemets ne semblent pas nécessaires

Pour décharger la bibliothèque avant une fin de session ou de script :

>
detach(package:ggplot2)

On trouve sur Internet des pages plus ou moins bien faites sur l'utilisation des fonctions des bibliothèques. Pour trouver de la documentation sur la bibliothèque ggplot2, saisir r ggplot2 dans le moteur de recherche DuckDuckGo.