Un peu d’histoire et quelques grands principes

R est un langage utilisé pour le traitement de données statistiques créé au début des années 1990 par deux chercheurs de l’université d’Auckland, Ross Ihaka and Robert Gentleman. Il reprend de très nombreux éléments du langage S créé par le statisticien américain John Chambers à la fin des années 1970 au sein des laboratoires Bell.

La première version stable a été rendue publique en 2000 : d’abord principalement diffusé parmi les chercheurs et les statisticiens “académiques”, R est aujourd’hui de plus en plus utilisé au sein des Instituts nationaux de statistiques.

R : un logiciel libre

À la différence d’autres logiciels de traitement statistique (SAS, SPSS ou Stata notamment), R est un logiciel libre : sa licence d’utilisation est gratuite et autorise chaque utilisateur à accéder, modifier ou redistribuer son code source. En pratique, il est maintenu par une équipe (la R Core Team) qui veille à la stabilité du langage et de ses implémentations logicielles.

Une des conséquences de cette philosophie “libre” présente dès les premières années du développement du langage est le rôle qu’y jouent les modules complémentaires, ou packages. Au-delà des “briques” fondamentales de la R Core Team, plusieurs milliers de packages sont disponibles et librement téléchargeables via le Comprehensive R Archive Network (ou CRAN) ou encore par le biais de plate-formes de développement collaboratif comme GitHub. Ces packages, dont l’installation est particulièrement simple dans R, enrichissent considérablement les fonctionnalités du logiciel et sont une de ses principales forces.


Remarque importante Comme de nombreux logiciels libres, R est très influencé par le fonctionnement du système d’exploitation Linux. À ce titre, certains éléments de sa syntaxe peuvent dérouter un utilisateur de Windows :

  • R est sensible à la casse : il distingue ainsi matable de MATABLE ou encore de maTable, même sous Windows (contrairement à SAS notamment) ;
  • dans R les chemins doivent utiliser des / et non des \ : ainsi, pour pointer vers le dossier V:\enquete\donnees il faut saisir dans R V:/enquete/donnees.

 

De manière plus générale, le fonctionnement de R est plus proche de celui d’un langage de programmation “classique” (Python, C, Java, etc.) que de celui des autres logiciels de traitements statistiques. Une manière d’introduire cet aspect fondamental du logiciel est de développer la célèbre citation de John Chambers:

To understand computations in R, two slogans are helpful:

  • Everything that exists is an object.

  • Everything that happens is a function call.

John Chambers

“Tout ce qui existe est un objet”

Tout ce qui existe et est manipulable dans R est un objet identifié par son nom et par son environnement de référence. Par défaut, tous les objets créés par l’utilisateur apparaissent dans l’environnement dit “global” (.GlobalEnv) qui est implicite, de façon analogue à la bibliothèque WORK de SAS.

Pour créer un objet, la méthode la plus simple consiste à assigner une valeur à un nom avec l’opérateur <-. Par exemple :

a <- 4

assigne la valeur 4 à l’objet a (dans l’environnement global). Dès lors, il est possible d’afficher la valeur de a et de la réutiliser dans des calculs :

# Affichage de la valeur de a avec la fonction print() ...
print(a)
  ## [1] 4

# ... ou tout simplement en tapant son nom
a
  ## [1] 4

# Utilisation de a dans un calcul
2 * a
  ## [1] 8

# Définition et utilisation de b
b <- 6
a * b
  ## [1] 24

Il est bien sûr possible d’assigner à un nom non pas une valeur numérique unique (comme ici 4 à a et 6 à b) mais des données provenant d’une table externe.

Exemple Le code suivant associe à l’objet reg les caractéristiques des régions dans le Code officiel géographique (COG) au 1er janvier 2017.

# Lecture du fichier du COG contenant le nom des régions
# et stockage dans l'objet dont le nom est `reg`
reg <- read.delim("reg2017.txt")
# Affichage de l'objet reg
reg
  ##    REGION CHEFLIEU TNCC                        NCC
  ## 1       1    97105    3                 GUADELOUPE
  ## 2       2    97209    3                 MARTINIQUE
  ## 3       3    97302    3                     GUYANE
  ## 4       4    97411    0                 LA REUNION
  ## 5       6    97608    0                    MAYOTTE
  ## 6      11    75056    1              ILE-DE-FRANCE
  ## 7      24    45234    2        CENTRE-VAL DE LOIRE
  ## 8      27    21231    0    BOURGOGNE-FRANCHE-COMTE
  ## 9      28    76540    0                  NORMANDIE
  ## 10     32    59350    4            HAUTS-DE-FRANCE
  ## 11     44    67482    2                  GRAND EST
  ## 12     52    44109    4           PAYS DE LA LOIRE
  ## 13     53    35238    0                   BRETAGNE
  ## 14     75    33063    3         NOUVELLE-AQUITAINE
  ## 15     76    31555    1                  OCCITANIE
  ## 16     84    69123    1       AUVERGNE-RHONE-ALPES
  ## 17     93    13055    0 PROVENCE-ALPES-COTE D'AZUR
  ## 18     94    2A004    0                      CORSE

 

Dans tous les cas, les objets créés sont stockés dans la mémoire vive de l’ordinateur (comme dans Stata), ce qui présente des avantages et des inconvénients :

  • (+) on ne modifie jamais les fichiers originaux, uniquement les objets chargés en mémoire ;
  • (+) les opérations sur les objets chargés peuvent être extrêmement rapides, car elles ne nécessitent pas de lire des données sur le disque ;
  • (-) à chaque lancement de R il faut recharger les données nécessaires en mémoire ;
  • (-) la taille totale des données chargées ne peut pas excéder celle de la mémoire vive installée (80 Go partagés sur un serveur AUS actuellement).

“Tout ce qui se produit est un appel de fonction”

Une fois les objets sur lesquels on souhaite travailler créés (i.e. les tables importées), R dispose d’un grand nombre de fonctions pour transformer ces données et mener à bien des traitements statistiques. Dans R une fonction est un type d’objet particulier : une fonction est identifiée par son nom (dans un environnement de référence) suivi de parenthèses.

Exemple La fonction ls() (sans argument) permet d’afficher les objets chargés en mémoire.

# Affichage des objets chargés en mémoire avec ls()
ls()
  ## [1] "a"   "b"   "reg"

Il y a pour l’instant trois objets en mémoire : a, b et reg.

Progresser dans la maîtrise de R signifie essentiellement étendre son “vocabulaire” de fonctions connues. Avec le temps, il est fréquent que l’on revienne sur d’anciens codes pour les simplifier en utilisant des fonctions découvertes entre temps (ou parfois en exploitant mieux les mêmes fonctions !).

 

Il est également extrêmement facile et courant dans R de créer ses propres fonctions.

Exemple La fonction monCalcul() renvoie le résultat de param1 * 10 + param2, où param1 et param2 sont deux nombres.

# Définition de la fonction monCalcul()
monCalcul <- function(param1, param2){
  resultat <- param1 * 10 + param2
  return(resultat)
}

# Test de la fonction monCalcul() avec les valeurs 1 et 3
monCalcul(1, 3)
  ## [1] 13

# Test de la fonction monCalcul() avec les valeurs a et 2
a
  ## [1] 4
monCalcul(a, 2)
  ## [1] 42

Quand on saisit uniquement le nom de la fonction (sans parenthèse), R affiche son code :

# Affichage du code de la fonction monCalcul()
monCalcul
  ## function(param1, param2){
  ##   resultat <- param1 * 10 + param2
  ##   return(resultat)
  ## }

À noter que rien ne distingue les fonctions pré-chargées dans le logiciel (comme read.delim() ou ls() utilisées précédemment) des fonctions créées par l’utilisateur. Il est ainsi tout à fait possible d’afficher le code de ces fonctions.

# Affichage du code de la fonction read.delim()
read.delim
  ## function (file, header = TRUE, sep = "\t", quote = "\"", dec = ".", 
  ##     fill = TRUE, comment.char = "", ...) 
  ## read.table(file = file, header = header, sep = sep, quote = quote, 
  ##     dec = dec, fill = fill, comment.char = comment.char, ...)
  ## <bytecode: 0x8f0d658>
  ## <environment: namespace:utils>

C’est une conséquence du caractère “libre” du logiciel : non seulement le code des fonctions pré-chargées est consultable, mais il est également modifiable.

Exemple Il est tout à fait possible dans R (même si cela n’a a priori pas grand intérêt…) de modifier la signification des signes arithmétiques (qui comme toutes les autres opérations dans R correspondent à des fonctions).

# On décide d'associer au signe + l'opération effectuée habituellement 
# par le signe - :
`+` <- `-`

# Le signe + est désormais associé à la soustraction :
2 + 2
  ## [1] 0

Cet exemple illustre la très grande souplesse de R comme langage : tous ses aspects sont modifiables, si bien qu’il est possible de développer facilement des programmes R parfaitement adaptés aux besoins les plus spécifiques.

 

Découverte de l’interface

En tant que tel, R est un langage susceptible d’être implémenté dans de nombreuses interfaces. Le choix est fait ici de présenter d’abord son implémentation minimale (en mode “console”) puis une implémentation beaucoup plus complète par le biais du programme RStudio. Dans tous les cas, la plate-forme utilisée est Windows.

Effectuer des manipulations de base dans la console

Par défaut sous Windows, R est fourni avec une interface graphique minimiale (Rgui.exe), dont la fenêtre principale est une console, c’est-à-dire un terminal dans lequel taper des instructions (comparable à l’invite de commandes Windows). Les instructions sont à taper après le signe > en rouge.

Interface fenêtrée de R sous Windows

Interface fenêtrée de R sous Windows

Toutes les commandes peuvent être passées au logiciel par le biais de la console, même si en pratique les commandes les plus longues sont stockées et soumises depuis un fichier de script (cf. la sous-partie suivante). En particulier, il est fréquent d’effectuer dans la console:

  • des assignations et des rappels de valeur : le signe <- permet d’assigner des valeurs à des noms pour être réutilisées ultérieurement. Quand une valeur est assignée à un nom, il suffit de taper le nom dans la console pour afficher la valeur.

  • des opérations sur les objets en mémoire :
    • la fonction ls() affiche tous les objets en mémoire ;
    • la fonction str(a) affiche les caractéristiques (ou encore la structure) de l’objet a (son type, sa longueur, etc.) ;
    • la fonction rm(a) supprime l’objet a.
  • des requêtes pour l’aide : pour afficher l’aide sur une fonction dont le nom est maFonction, il suffit d’utiliser help(maFonction) ou plus simplement ? maFonction.

  • des opérations simples : le tableau ci-dessous présente quelques opérations arithmétiques et les symboles correspondant en R.

    Code R Résultat
    a + b Somme de a et b
    a - b Soustraction de b à a
    a * b Produit de a et b
    a / b Division de a par b
    a ^ b a puissance b
    a %/% b Quotient de la division euclidienne de a par b
    a %% b Reste de la division euclidienne de a par b
    sqrt(a) Racine carrée de a

 

Cas pratique 1.1 Convertir une durée de secondes en minutes-secondes

Il est souvent très utile de mesurer et d’afficher la durée d’un traitement un peu long (script exécuté régulièrement par exemple). La fonction system.time() de R n’affiche néanmoins que le temps écoulé en secondes, ce qui n’est guère lisible. L’objectif de ce cas pratique est de convertir une durée de secondes en minutes-secondes.

  1. Ouvrez une session AUS (en utilisant votre idep et votre mot de passe) et lancez le programme R (pas Rstudio).

  2. Dans la console, associez la valeur 2456 à l’objet duree. C’est sur cette durée (en secondes) que vont porter tous les calculs. Une fois assignée, rappelez la valeur de duree dans la console.

     

  3. Calculez le nombre de minutes correspondant à la valeur de duree. Comment obtenir un nombre entier (cf. le tableau des opérations arithmétiques) ? Associez cette valeur à l’objet min.

     

  4. Calculez le nombre de secondes restantes une fois le nombre de minutes déterminé. Vous pouvez utiliser la flèche \(\uparrow\) du clavier pour rappeler et modifier le code que vous venez de soumettre. Associez cette valeur à l’objet sec.

     

  5. Utilisez la fonction help() (ou de façon équivalente ?) pour recherchez de l’aide sur la fonction paste(). Que se passe-t-il quand vous soumettez le code

    paste("La durée est de", duree, "secondes.")

    En utilisant tous ces éléments, afficher dans la console le texte :

    [1] "Le traitement a duré 40 minutes et 56 secondes."