Pourquoi R est-il si difficile à apprendre ?

Démonstration de maths
Auteur : Vincent Guyader
Tags : Actualités, Ressources
Date :

 

Cet article est la traduction libre de l’article de Bob Muenchen why R is hard to learn, merci à lui pour son aimable autorisation de le reprendre ici. Merci à Charlotte et Diane pour leurs très précieuses relectures

logo du langage de programmation et logiciel RR a la réputation d’être difficile à apprendre. Cela s’explique par le fait qu’il est radicalement différent des autres logiciels de traitement de données, qu’il est extrêmement puissant et polyvalent. Mais aussi, comme pour n’importe quel logiciel, à cause de certains choix de conception qui, avec le recul, auraient pu être meilleurs. R est très différent au premier abord si vous avez pour habitude d’utiliser un autre logiciel de statistique. C’est cette approche que j’utilise dans mes livres “R for SAS and SPSS Users” et “R for Stata Users” tout comme dans mes formations qui sont basées sur ces ouvrages.(NdT : livres anglophones de bob Muenchen)

Les critiques fréquemment adressées à R pendant mes formations sont listées ci-dessous… j’espère ainsi que les débutants seront prévenus, mais qu’ils prendront malgré tout conscience que beaucoup de ces ennuis sont accompagnés d’avantages et qu’ils envisageront d’utiliser les solutions offertes dans les différents packages que je propose. Comme beaucoup le disent, R rend facile les choses compliquées, et complique les choses simples. Toutefois, certains packages aident à rendre facile les choses simples.

Une aide inutile

Les fichiers d’aide R sont souvent denses et contiennent normalement de nombreux exemples. Cependant ils ne sont vraiment pas écrits pour les débutants ! Le fichier d’aide d’une des premières commandes que les débutants en programmation apprennent – print()– est mon exemple préféré. Le fichier d’aide de SAS indique pour la procédure print: ce qui est assez précis. Le fichier d’aide de R nous dit :

“print prints its argument and returns it invisibly (via invisible(x)). It is a generic function which means that new printing methods can be easily added for new classes.”

 

Ce qui donne en français :

print affiche ses arguments et les retourne de manière invisible (via invisible(x)). Il s’agit d ‘une fonction générique ce qui signifie qu’une nouvelle méthode print peut être rajoutée à une nouvelle classe”.

Le lecteur n’a plus qu’à s’enquérir de ce qu’est une sortie “invisible” et de ce que sont les méthodes et les classes. Les fichiers d’aide peuvent vous en dire plus sur ce que sont les méthodes, mais pas sur les classes. Vous devez savoir chercher de l’aide sur les classes pour avoir cette information.

Un autre aspect rebutant des fichiers d’aide de R émerge avec la capacité de R à rajouter de nouvelles possibilités (des méthodes) à certaines fonctions lorsque vous chargez un package. Cela signifie que vous ne pouvez pas simplement lire un fichier d’aide, le comprendre et avoir compris cette fonction pour toujours. Cela signifie par contre que vous avez moins de commandes à apprendre. Par exemple, une fois que vous avez appris à utiliser la fonction predict et que vous chargez un nouveau package, cette fonction peut acquérir de nouvelles méthodes afin de gérer les modèles traités spécifiquement avec ce nouvel outil. Ainsi un débutant en R devra apprendre beaucoup plus qu’un débutant SAS ou SPSS avant de trouver les fichiers d’aide utiles. Cela dit, il existe un vaste éventail de tutoriels, d’ateliers et de livres disponibles, pour la plupart gratuits, pour permettre aux débutants de franchir cette barrière.

Des noms de fonctions et de paramètres trompeurs

La partie la plus compliquée pour les gens qui apprennent R est quand les fonctions ne font pas les choses “logiques”, auxquelles on s’attendrait (lorsque l’on a programmé dans d’autres langages, NdT). Par exemple pour trier un jeu de données, les utilisateurs de SAS, SPSS et Stata utilisent tous la commande sort() qui porte bien son nom. Une fois sur R, ils cherchent la même commande, et il y en a bien une qui porte le même nom. Cependant elle ne trie pas les jeux de données! Au lieu de cela elle trie les vecteurs, ce qui est souvent assez dangereux à faire. Dans R, la fonction order permet de trier un jeu de données, mais elle le fait d’une façon un peu alambiquée. Cela dit le package {dplyr} propose la fonction arrange() qui trie les jeux de données et qui est plutôt facile à utiliser.

Peut-être que le plus gros choc est à venir, c’est à dire quand le nouvel utilisateur découvre que le tri n’est en fait pas toujours nécessaire dans R. Alors que d’autres outils demandent d’avoir des données triées avant de pouvoir faire les 3 actions classiques : (1) résumer/agréger des données, (2) répéter une analyse pour chaque groupe et (3) faire une jointure entre bases. R n’a pas besoin que l’utilisateur trie explicitement ses jeux de données avant de lancer ces actions !

La simple fonction if()</emcode est une autre commande qui trouble les débutants. Elle est utilisée (entre autres) pour recoder des variables dans d'autres logiciels, tandis que dans R if() contrôle l'exécution des commandes. C'est ifelse() qui permet de faire des actions telles que le recodage des variables.

Trop de commandes

Les autres logiciels de statistique ont relativement peu de commandes mais chacune d’entre elle a des options pour maîtriser leurs sorties. La démarche de R est à l’opposé et il faut un peu de temps pour s’y habituer. Par exemple, lorsqu’une régression linéaire est faite avec SAS ou SPSS tout est défini à l’avance, et le résultat une sortie complète : coefficient, table d’analyse de variance etc. Par contre lorsqu’un modèle est implémenté dans R, une commande summary() donne l’estimation des paramètres tandis qu’une autre (anova()) donne la table d’analyse de variance. D’autres commandes telles que coefficients ne donneront qu’une partie du modèle. Il y a donc plus de commandes à connaître, mais aussi moins de paramètres à maîtriser pour chacune.

Une syntaxe incohérente

Puisque tout le monde est libre d’ajouter de nouvelles fonctionnalités à R, la syntaxe utilisée par les différents packages de R est un peu hétéroclite. Par exemple, les deux blocs de code ci-dessous font à peu près la même chose, mais en utilisant des syntaxes radicalement différentes. Ce type de divergence est classique dans R, et il n’y a aucun moyen d’éviter cela puisque tout le monde peut ajouter ce qu’il souhaite.

library("Deducer")
descriptive.table(
vars = d(mpg,hp),
data = mtcars,
func.names =c("Mean", "Median",
"St. Deviation", "Valid N",
"25th Percentile", "75th Percentile"))

library("RcmdrMisc")
numSummary(
data.frame(mtcars$mpg, mtcars$hp),
statistics = c("mean", "sd", "quantiles"),
quantiles = c(.25, .50, .75))

Crise identitaire

Tous les logiciels de statistique nomment leurs variables, mais R est particulier en ce sens qu’ il nomme aussi les lignes. Cela implique un apprentissage de la gestion des noms de lignes ET des noms des colonnes. qu’il est nécessaire d’apprendre à gérer aussi bien les noms des lignes que les noms des variables. Par exemple, à la lecture d’un fichier CSV, les noms de variables sont sur la première ligne et tous les logiciels de statistique peuvent lire ces noms.

Un identifiant (un ID ou un numéro) apparaît souvent dans la première colonne de ce type de fichiers. Dans R, si cette colonne n’a pas de nom, R supposera que c’est un nom de variable d’identification et convertira alors sa valeur en noms de lignes. Cependant, si elle a un nom (ce que tous les autres logiciels demanderaient) alors il faut donner à R des paramètres pour qu’il ajoute ces valeurs ou celles d’une autre variable dans les noms de lignes. Une fois que vous faites cela, le nom d’origine de la variable d’identification disparaît. L’avantage de cet attitude étrange est que quand une analyse ou un graphique nécessite d’identifier une observation, R sait automatiquement ou aller chercher cette information. Cela permet à R de se passer de la variable ID nécessaire à SAS (ex: PROC CLUSTER).

Bien que cela semble un « compromis » rentable, cela reste délicat car il faut que les noms de lignes soient uniques. Cela signifie qu’il n’est pas possible de maintenir les noms de lignes originales lorsque deux fichiers qui ont les mêmes variables sont empilés si vous avez mesuré les mêmes observations à deux moments (par exemple avant et après un traitement).

Cela signifie également que le regroupement de sorties d’analyses effectuées par groupe peut être difficile, bien que le package {broom} gère cela pour nous. Le fameux package {dplyr} remplace le nom des lignes par des caractères correspondant à des entiers relatifs consécutifs : “1”, “2”, “3” …. Mon conseil est de gérer vos propres variables d’identification en tant que variables standard et les mettre dans le nom des lignes seulement quand cela est avantageux pour l’usage d’une fonction.

Un contrôle dangereux des variables

Dans R, une analyse peut utiliser des variables provenant de plusieurs jeux de données. Cela nécessite généralement que les observations soient identiques dans chaque jeu de données. Au fil du temps j’ai vu un nombre incalculable de clients coller des bases de données en étant persuadés que chacune contenait les mêmes observations, exactement dans le même ordre. Cependant, un contrôle rapide montrait qu’il n’en était rien. Il est toujours plus sûr de fusionner les bases en utilisant une clef (ID par exemple), quand c’est possible. Du coup en autorisant cela R semble prêcher pour la catastrophe, et je recommande, quand c’est possible de fusionner les bases par clef avant de faire une analyse.

De drôles de manières d’analyser plusieurs variables

Une des premières fonctions qu’apprennent les débutants est summary(x). Comme cela se devine, elle donne les statistiques descriptives de la variable x. C’est plutôt enfantin. L’erreur consiste à taper summary(x,y) pour analyser 2 variables. En effet, cette instruction est fausse car beaucoup de fonctions R, dont celle-ci, n’acceptent qu’un seul objet. La solution est de regrouper ces 2 objets dans un seul, dans un « data frame » : summary(data.frame((x,y)). La généralisation ne se fait pas en appliquant la fonction de une à plusieurs variables, mais d’un objet (qui est une variable) à un autre objet (ici, un jeu de données).

Si c’était aussi simple que ça, cela ne serait pas si compliqué à apprendre. Malheureusement, les fonctions de R ne sont pas homogènes en ce qui concerne le type et le nombre d’objets qu’ils acceptent. A l’opposé de la fonction summary() et de l’exemple précédent, la fonction max() de R peut accepter autant de variables que souhaitées, il suffit de les séparer par des virgules.

Un processus de nommage et de renommage de variables outrageusement compliqué

Les apprenants sont souvent surpris quand ils apprennent comment R nomme et renomme ses variables. Comme R stocke les noms dans un vecteur de chaînes de caractères, n’en renommer même qu’une seule signifie d’être obligé dans un premier temps de localiser ce nom dans ce vecteur avant de pouvoir mettre un nouveau nom à cette position. C’est beaucoup plus compliqué que la simple instruction nouveauNOM=ancienNOM utilisé dans de nombreux autres langages. Bien que cette façon de faire soit plus compliquée, elle apporte de grands avantages. Par exemple, il est aisé de copier les noms des variables d’une base à l’autre. Il est également possible d’utiliser utiliser la panoplie des outils de manipulation de chaînes de caractères (comme les expressions régulières) afin de multiplier les tactiques pour changer les noms. Ces façons de procéder sont impossibles à mettre en œuvre (ou du moins bien plus compliquées à mettre en oeuvre) dans les autres langages.

Si le jeu de données est issu d’un fichier texte, je recommande de simplement ajouter les noms dans la première ligne du fichier. Si vous avez besoin des les renommer par la suite, je recommande la fonction rename() du package {dplyr}. Et vous pouvez passer à la méthode native de renommage de R quand vous avez besoin de plus de flexibilité.

Faible capacité à sélectionner des variables

La majorité des logiciels de traitement de données permettent de sélectionner les variables qui sont les unes a coté des autres dans un jeu de données (ex: A-Z ou A TO Z), qui partagent un préfixe commun (ex :varA,varB,…) ou qui se terminent par un nombre (ex x1-x25, sans qu’elles soient nécessairement les unes à côté des autres). R ne dispose pas nativement de fonctionnalités qui permettent de faire cela facilement. Toutefois, même si elles ne sont pas natives, R offre bien plus de souplesse en matière de sélection de variables que les autres logiciels au prix d’un peu de programmation.. Ces fonctionnalités (et d’autres encore) sont fournies dans le package {dplyr} (fonction select()).

De trop nombreuses façons de sélectionner des variables

Si la variable x est stockée dans mondata et que vous voulez calculer les statistiques descriptives de x, la plupart des logiciels ne propose qu’une seule façon de faire, comme par exemple "var x;" en SAS. Dans R on peut faire ça de différentes façons :


mondata$masomme <- mondata$x + mondata$y
mondata$masomme <- with(mondata, x + y)
mondata["masomme"] <- mondata["x"] + mondata["y"]
attach(mondata)
  mondata$masomme <- x + y
detach(mondata)
mondata <- within(mondata,
  masomme <- x + y
)
mondata <- transform(mondata, masomme = x + y)
library("dplyr")
  mondata <- mutate(mondata, masomme = x + y)
  mondata <- mondata %>% mutate(masomme = x + y)

Pour compliquer la chose, si on demandait simplement la moyenne au lieu des statistiques descriptives, beaucoup de ces instructions ou syntaxes aboutiraient à un message d’erreur car elles sélectionnent x d’une façon que la fonction mean() n’accepte pas.

Pour empirer les choses, les exemples précédents fonctionnent avec des données stockées sous forme de data frame (que l’on peut traduire par « cadre de données » ; ce que la majorité des logiciels appelle dataset pour « jeu de données » NdT) mais toutes ne fonctionnent pas avec les données stockées sous forme d’une matrice. Pourquoi y a-t-il tant de façon de sélectionner des variables ? Si R propose de si nombreuses structures de données c’est pour une plus grande flexibilité. Et chacune peut utiliser une approche légèrement différente pour sélectionner des variables. Quand vous intégrez le langage de calcul matriciel dans le langage de programmation classique, plutôt que de les voir comme un langage externe comme dans SAS/IML, cela exige que vous compreniez ce qui est souvent cachée, jusqu’à ce que vous en avez besoin, dans d’autres logiciels. Les derniers exemples cités viennent du package {dplyr}, qui rend la sélection de variable plus simple, mais qui, bien sûr, demande un peu d’apprentissage.

Trop de façons de transformer les variables

Les logiciels de statistique ne proposent généralement qu’une seule manière de transformer des variables. SAS a son data step, SPSS a l’instruction COMPUTE etc . R a plusieurs approches, certaines sont présentées ci-après.

Sont présentées ici quelques façons qu’à R de créer une nouvelle variable appelée “masomme” en additionnant 2 variables x et y.

mondata$masomme <- mondata$x + mondata$y
mondata$masomme <- with(mondata, x + y)
mondata["masomme"] <- mondata["x"] + mondata["y"]
attach(mondata)
  mondata$masomme <- x + y
detach(mondata)
mondata <- within(mondata,
  masomme <- x + y
)
mondata <- transform(mondata, masomme = x + y)
library("dplyr")
  mondata <- mutate(mondata, masomme = x + y)
  mondata <- mondata %>% mutate(masomme = x + y)

Certaines sont des variations des différentes manières de sélectionner des variables, certaines utilisent la fonction attach qui nécessite l’usage de “mondata$” (ou un équivalent) pour s’assurer que la nouvelle variable soit stockée dans le jeu de données d’origine.

En laissant ces variations de coté, d’imaginer que la nouvelle variable sera stockée automatiquement dans le jeu de données (ce n’est pas le cas!) est une grande source de confusion pour les débutants.La fonction within utilisée est comparable à la fonction with, mais celle-ci autorise les modifications de variables alors que with, non.

Toutes les fonctions n’acceptent pas toutes les variables

Dans la majorité des logiciels de traitement de données une variable est une variable, et toutes les procédures les acceptent. Dans R, cependant, une variable peut être un vecteur, un facteur, une partie d’un jeu de données ou même un élément d’une structure complexe de R appelée liste. Pour chaque fonction vous devez comprendre ce sur quoi elle accepte de travailler. Par exemple, la majorité des fonctions de statistique basique (pour la moyenne, médiane etc) va prendre en entrée les variables sous forme de vecteur. Elles vont aussi accepter les variables d’un jeu de données ou d’une liste, mais seulement si vous les sélectionnez de manière à ce que, à la volée, elles deviennent des vecteurs. Cette complexité est un effet secondaire inévitable du puissant ensemble de structure de données de R qui comprend vecteur, facteur, matrice, jeu de données, tableau et liste. Bien que cela rajoute de la difficulté, cela offre un large éventail de perspectives. Par exemple, les variables qualitatives qui sont stockées en tant que facteur peuvent être inclues automatiquement dans un modèle de régression, et R va automatiquement générer les variables de telle sorte qu’elles s’intègrent de façon adéquate au modèle.

Des noms prêtant à confusion/des noms déroutants

Les noms doivent parfois être entre guillemets, mais d’autres non. Par exemple pour installer un package et le charger en mémoire il est possible d’ utiliser successivement ces 2 étapes, syntaxiquement incohérentes:

install.packages("dplyr")
library(dplyr)

Il est possible de rendre ces commandes homogènes en ajoutant des guillemets autour de “dplyr” dans la seconde commande, mais pas en supprimant les guillemets de la première ! Et pour enlever un package de la mémoire vous devez utiliser la commande suivante, qui appelle le package encore d’une autre façon (avec ou sans guillemets)

detach(package:dplyr)

Faible capacité à sélectionner des données

La première chose à faire dans toutes analyses de données, et de sélectionner le jeu de données sur lequel on va travailler. La plupart des autres logiciels ont une façon de préciser le jeu de données qui est (1) facile, (2) sûre et (3) cohérente. R propose de nombreuses façons de sélectionner un jeu de données, mais aucune ne regroupe ces 3 critères. Faire référence aux variables en écrivant mondata$mavar fonctionne dans de nombreuses situations, mais il est lassant de toujours devoir taper “mondata” encore et encore.

R possède une fonction attach, mais son usage est un peu délicat : elle donne aux débutants l’impression que les nouvelles variables sont stockées dans la base (par défaut, elle ne le seront pas) et que R va chercher des variables dans ce jeu de données avant d’aller regarder ailleurs (il ne le fait pas toujours). Certaines fonctions proposent un paramètre data, mais pas toutes. Et même quand une fonction le propose, cela ne marche seulement que si vous précisez une équation de modèle avec (ex : les tests appariés n’ont pas besoin d’équation de modèle).

Pourquoi est-ce si facile dans d’autres logiciels, mais si compliqué dans R, d’où cela vient-il ? C’est en partie le prix à payer pour avoir une grande flexibilité. R est le seul logiciel que je connaisse qui permet d’inclure des variables de plusieurs jeux de données dans une même analyse. Donc il doit être possible de changer de jeu de données au milieu d’une analyse. Il est vrai toutefois que cela peut être un de ces choix de conception qui auraient pu être mieux traités. Par exemple il aurait pu être mis en place un paramètre data dans toutes les fonctions avec une option globale qui permet de définir un jeu de données par défaut, comme dans SAS.

La phobie des boucles

R dispose de boucles pour contrôler l’exécution des commandes, mais on demande, principalement aux débutants, de ne pas les utiliser. Alors que les boucles sont indispensables pour utiliser la même fonction sur plusieurs variables, cela semble un étrange.. En fait, à la place, R utilise la famille des “apply“. Elles permettent de demander à R d’appliquer la fonction en ligne ou en colonne. C’est une gymnastique mentale à faire, mais le résultat est le même. L’avantage de cette façon de faire c’est qu’il est parfois plus facile à écrire et à comprendre une fonction apply. (NdT : ou pas…)

Les fonctions qui agissent comme des procédures

Beaucoup d’autres logiciels de statistique tels que SAS, SPSS et Stata ont des procédures ou instructions qui réalisent des analyses pour toutes les observations.. Ils ont aussi des fonctions qui font une opération par ligne, comme calculer la moyenne de scores pour toutes les observations du jeu de données. Mais R n’a que des fonctions, et de nombreuses fonctions qui peuvent faire les deux. Comment s’en sortir avec ca ? Les fonctions permettent de travailler préférentiellement en ligne ou en colonne, mais pour la majorité vous pouvez utiliser les fonctions “apply” pour forcer l’une ou l’autre des directions. Donc il est vrai que dans R les fonctions se comportent à la fois comme des procédures ou des fonctions. Si vous venez d’un autre logiciel, c’est une nouvelle idée qui peut vous paraître insensée.

Des Noms de fonction incohérents

Tous les langages ont leurs incohérences. Par exemple, il a fallu une dizaine d’année aux développeurs de SPSS pour proposer un éditeur avec contrôle de syntaxe. J’ai entendu dire par l’un d’entre eux que cela aurait été fait plus tôt s’il n’y avait pas eu autant d’incohérences dans le langage. SAS a lui aussi son lot d’incohérences, avec le paramètre OUTPUT pour certaines procédures et OUT pour d’autres. Cependant, je soupçonne R d’avoir probablement beaucoup plus d’incohérences que les autres car il lui manque une convention pour nommer les objets et les fonctions.

Voici quelques exemples natifs de R

 

names, colnames
row.names, rownames
rowSums, rowsum
rowMeans #(rowmean n'existe pas)
browseURL, contrib.url, fixup.package.URLs
package.contents, packageStatus
getMethod, getS3method
read.csv et write.csv, load et save, readRDS et saveRDS
Sys.time, system.time

Quand on rajoute les packages, on peut tomber sur de réelles “énormités”. Par exemple, R a une fonction native : reshape, le package Hmisc a une fonction reShape (la majuscule est importante), et il existe 2 packages reshape et reshape2 qui réorganisent des données, mais aucun des deux ne contient une fonction qui s’appellerait reshape !

Une prise en compte étrange des données manquantes

Dans tous les logiciels de statistique que je connais, les données manquantes sont traitées de la même façon : elles sont exclues automatiquement quand (1) on sélectionne des observations (2) on fait des analyses. Quand on sélectionne des observations, R y laisse les données manquantes ! Par exemple disons que vous avez ce jeu de données :

 

Genre Anglais Mathématique
1 Masculin 85 82
2 Masculin 72 87
3 75 81
4 Feminin 77 78
5 Feminin 98 91

 

Si vous sélectionnez les hommes avec mondata[mondata$genre == “Masculin”, ], R va renvoyer les 3 premières lignes et va utiliser un NA pour la troisième ligne. Pourquoi créer une donnée manquantes là ou il n’y en avait pas avant ? Tout se passe comme si les créateurs de R ont considérés les données manquantes comme étant inhabituelles et ont pensé que vous deviez être averti de leur existence. Dans mon expérience, les données manquantes sont si courantes que si j’ai un jeu de données qui n’en a pas, je suis suspicieux et pense que quelqu’un a oublié de mettre en place un code pour noter les données manquantes. Pour y remédier, which est une fonction qui nous donne les indices des observations pour lesquels la relation logique est vraie : mondata[which(mondata$genre == “Masculin”), ]

 

Lorsque l’on fait des analyses plus complexes, en utilisant ce que R appelle des “fonctions de modélisation”, les valeurs manquantes sont exclues automatiquement. Cependant, quand on utilise des fonctions simples, telles que moyenne ou médiane, il fait l’inverse et renvoie une donnée manquante en résultat si la variable contient ne serait-ce qu’une seule donnée manquante. On peut passer outre ce soucis en précisant na.rm=TRUE sur chacune des fonctions, mais pourquoi devriez vous faire cela? Alors qu’il y a des options qui permettent de contrôler de nombreuses choses telles que la largeur des lignes en sortie, il n’ y a pas d’option qui permettent d’éviter ce désagrément. Il n’est pas compliqué de créer sa propre fonction dans laquelle les données manquantes sont supprimées par défaut, mais cela semble disproportionné pour une problématique si basique.

Cela ne semble pas apporter d’avantages à R, il y a des petits inconvénients avec lesquels les utilisateurs de R doivent apprendre à vivre.

Une étrange façon de compter les valeurs manquantes et les valeurs valides

La fonction length, l’une des fonctions qui aurait un intérêt certain à exclure les données manquantes, ne peut pas les exclure ! Alors que la majorité des logiciels incluent une fonction qui s’appelle quelque chose comme n ou nvalide, l’approche de R pour compter les réponses valides est de (1) vérifier si la valeur est une donnée manquante avec la fonction is.na puis (2) utiliser le symbole “!” pour trouver les non-manquantes. Vous devez savoir que (3) cela génère un vecteur de VRAI/FAUX qui correspondent respectivement aux valeurs numérique 1 et 0. Ensuite vous devez les sommer avec la fonction sum. C’est une affreuse succession de complexité comparativement à n(x). Cependant, il est facile de créer votre propre fonction n ou d’ utiliser des packages qui en contiennent déjà une, comme la fonction n.valid du package prettyR.

Trop de structures de données

Comme indiqué précédemment, R a des vecteurs, facteurs, matrices, tableaux, des data.frame et des listes. Et ce n’est que le début ! Les fonctions de modélisation créent beaucoup de variations de ces structures et en fabriquent aussi de totalement nouvelles. Les utilisateurs sont libres de fabriquer leurs propres structures, et certaines sont devenues plutôt populaires. En complément de ces structures arrivent des fonctions de conversion qui permettent de passer un objet d’un type à l’autre, quand cela est possible. Etant donné que les autres logiciels s’en sortent avec un seul type de structure, pourquoi se faire tant de mal ? Si vous ajoutez les différents types de structures qui existent dans les langages matriciels des autres logiciels, vous verrez autant de complexité induite.

Des dimensions déformées

Les objets bidimensionnels peuvent facilement devenir des objets unidimensionnels. Par exemple cette façon de sélectionner les mâles utilise la variable “genre” en tant que sous-partie d’un jeu de données à 2 dimensions, il faut donc utiliser une virgule à la suite de la condition logique :

 

with(Talent[Talent$Genre == "Masculin", ],
summary(
data.frame(Anglais, Lecture)
)
)

 

Mais dans cette façon très similaire de faire la même chose, “genre” est utilisé en tant que vecteur unidimensionnel et donc rajouter une virgule (qui implique une seconde dimension) aboutira à un message d’erreur.

 

with(Talent,
summary(
data.frame(
Anglais[Genre == "Masculin"],
Lecture[Genre == "Masculin"]
)
)

 

Des analyses par groupes difficiles à mettre en oeuvre

La plupart des logiciels vous permettent de répéter une analyse simplement en ajoutant une commande du type by group. La façon de procéder native de R est beaucoup plus alambiquée. Cela demande de créer une fonction de type macro qui fait l’analyse dont vous avez besoin. Cette fonction est ensuite appliquée par groupe. Les autres langages vous épargnent ce type de programmation tant que vous n’avez pas à faire de choses complexes.

Des sorties pauvres

Les sorties de R sont souvent peu riches. Par exemple, lorsque l’on fait un tableau croisé, les autres logiciels renvoient aussi bien les comptages que les pourcentages en ligne et en colonne, les comptages marginaux etc. La fonction table, native de R, (ex : table(a,b)) ne renvoie que les comptages. L’explication d’une sortie sans fioritures est qu’elle peut être utilisée en tant que valeur d’entrée pour une autre analyse. Par exemple, obtenir un diagramme en bâtons à partir d’un tableau de contingence est aussi simple que barplot(table(a,b)). Cette approche tronçonnée est ce qui permet à R de s’affranchir d’un système séparé de gestion des sorties comme SAS’ ODS ou SPSS’ OMS. Mais il y existe des packages qui proposent des sorties plus complètes très comparables à celle proposées par les autres logiciels. Certains sont proposées ici.

Des sorties non mises en formes

Les sorties par défaut de SAS et SPSS sont bien formatées et sont faciles à lire ainsi qu’a copier-coller en tant que tableau dans un traitement de texte. Toutes les sorties peuvent être configurée comme journal de bord (ou autre format) simplement en cochant l’option ad hoc. Non seulement R manque de sorties structurées par défaut, mais ne propose pas de tabulations entre les colonnes non plus. De fait, le débutant copie la sortie dans un traitement de texte et sélectionne une police à chasse fixe (non proportionnelle) pour garder les colonnes alignées.

R offre la possibilité de belles sorties mais il faut pour cela utiliser des packages complémentaires tels que comprageGroups, knitr, pander, sjPlot, sweave, texreg, xtable etc. En réalité sa capacité à mettre en forme des sorties complexes (par exemple montrant des modèles multiples) est meilleure que dans tous les autres logiciels que j’ai expérimenté.

Une gestion complexe des sorties

La gestion des sorties est très liée aux analyses par groupe. Dans le cas le plus simple, vous pourriez faire une analyse et utiliser des paramètres de sortie pour sélectionner ce que vous voulez afficher. R inverse ce processus classique en nous présentant que très peu d’information et en nous laissant lui demander des sorties plus complètes après la création du modèle (comme l’approche de Stata)

Cependant, l’affichage des sorties d’une analyse ne correspond pas toujours au résultat voulu. Les sorties nécessitent souvent des manipulations complémentaires. Par exemple, dans mon université nous faisons toujours le même modèle de régression sur les salaires pour chacun des 250 départements. Nous ne nous intéressons pas à la majorité des résultats, nous voulons seulement voir les résultats pour les quelques départements dans lesquels les salaires semblent dépendre du genre ou de l’ethnie. Bien sûr nous espérons n’en trouver aucun ! R a un type de données spécial appelé liste qui est idéal pour stocker sorties aussi complexes. Cependant chaque type de modélisation donne une liste qui est unique avec des éléments de sortie stockés dans différents types de données avec des noms non homogènes.

Par exemple, la probabilité critique de 3 différents type d’analyse peut être appelé “p”,”pvalue” ou encore “p.value”. Par chance un package nommé broom a des commandes qui permettent de convertir une sortie en data frame et de standardiser les noms. A partir de cela vous pouvez faire toutes les analyses complémentaires que vous voulez.

La complexité de R n’est ici pas sans avantage. il serait en effet relativement facile pour moi de faire 2 modèles de régression par groupe, de sauvegarder la sortie et ensuite de faire une analyse complémentaire qui compare pour chacun des groupes les 2 modèles. Cela serait un défi pour la plupart des logiciels de statistique (voir l’aide de la fonction do du package plyr par exemple )

Une façon obscure de nettoyer la mémoire

Un autre fonctionnement énigmatique de R est la façon dont il purge son espace de travail dans la mémoire de votre ordinateur. Alors qu’un simple clear aurait pu suffire, la mentalité de R est de d’abord demander un listing des objets en mémoire et ensuite seulement de supprimer cette liste : rm(list=ls()). Qu’avez-vous besoin de savoir pour comprendre cette commande ? Vous avez besoin de savoir (1) que la commande ls() liste les objets en mémoire, (2) ce qu’est un vecteur de caractères car (3) la fonction ls() renvoie le nom des objets dans un vecteur de caractères, que (4) la fonction rm supprime les objets et (5) que le paramètre list ne demande pas d’information stockée sous forme de liste mais plutôt sous forme de vecteur. Cela fait beaucoup de chose à comprendre pour une simple commande.

Cette manière de faire a tout de même des avantages. La commande qui liste les objets en mémoire permet de chercher efficacement les motifs de noms d ‘objet que vous voulez supprimer.

Heureusement, la populaire interface Rstudio propose une icône “balai” qui permet maintenant de vider la mémoire d’un simple clic.

Le manque d’interface graphique pour utilisateurs

Comme pour la majorité des logiciels de statistique la pleine puissance de R n’est accessible qu’à travers la programmation. Cependant contrairement aux autres logiciels R ne propose pas d’interface native pour aider les non-programmeurs à faire leurs analyses. Les 2 qui se rapprochent le plus de SPSS et Stata sont Rcommander et Deducer. Tandis qu’elles proposent suffisamment de méthodes d’analyse jusqu’au niveau licence, elles manquent d’options en comparaison avec une interface puissante. Le pire étant que les débutants doivent dans un premier temps se familiariser avec un environnement de programmation, se demander ensuite comment trouver et installer l’interface graphique avant de pouvoir la lancer. C’est un souci dans la mesure où ce type d’interface est à destination de personnes ayant un faible niveau en informatique.

Absence de bornes dans les usages

Jusqu’à présent j’ai listé les aspects principaux qui perturbent les débutants. Beaucoup d’entre eux viennent de la puissance et de la flexibilité de R.

On l’a vu, R intègre étroitement des commandes pour (1) la gestion des données, (2) l’analyse de données et la création de graphiques, (3) la création de macro (4) la gestion de sorties et (5) le calcul matriciel. Cette particularité, adossée à un large ensemble de structures de données et la facilité avec laquelle n’importe qui peut étendre ses capacités, fait de R un puissant outil pour l’analyse.

C’est tout à fait l’opposé qui est fourni par ses concurrents tels SAS, SPSS et Stata. L’avantage notable est qu’en réalité ils proposent des « contraintes bénéfiques ».

Ces logiciels utilisent un seul type d’entrée, fournissent un seul type de sortie, proposent peu de moyens pour sélectionner les variables, proposent une seule une façon de renommer les variables, n’ont qu’une seule façon de faire des analyses par groupe, et sont bornés par bien d’autres aspects. Leurs outils de macro et de calcul matriciels, leur systèmes de gestion de sorties, sont séparés ; si bien qu’ils sont presque invisibles pour les débutants et même pour les utilisateurs intermédiaires.

Ces bornes limitent ce que vous pouvez faire, et comment vous pouvez le faire, rendant le logiciel plus facile à apprendre et à utiliser, tout particulièrement pour ceux qui n’ont qu’un besoin occasionnel. Ils proposent des fonctions parfaitement en adéquation pour résoudre des soucis pour lesquels ils ont des réponses pré-programmées. Et l’ensemble de solutions qu’ils proposent est très large. (Stata propose aussi de nombreuses fonctions écrites par la communauté)

Conclusion

Il y a beaucoup d’aspects de R qui font qu’il est difficile à apprendre pour les débutants. Certains sont liés à la nature unique de R, certains sont liés à sa puissance, sa flexibilité et son extensibilité. D’autre sont liés à des points qui n’apportent pas vraiment d’avantage comparatif. Cependant sa puissance, sa gratuité et son coté “open-source” attire les développeurs, et son large éventail d’extensions ont abouti à un logiciel qui gagne en popularité.

R a été mon outil principal d’analyse de données depuis presque 10 ans maintenant, et j’y ai trouvé que les avantages avaient bien plus de valeur que les pécadilles listées ici. Si vous programmez en SAS, SPSS ou Stata et que vous y êtes à l’aise, alors je vous recommande de prendre le temps d’essayer R pour voir si vous l’appréciez. J’espère que cet article va vous aider à vous préparer aux pièges sur lesquelles vous êtes susceptibles de vous heurter en expliquant comment certains d’entre eux offrent des avantages à long terme, et en offrant une sélection de packages adéquats soulager/rendre la moins douloureuse possible votre transition. Cependant si vous utilisez un de ces langages mais que vous n’êtes pas à l’aise, alors apprendre R n’est peut-être pas pour vous.

Ne vous inquiétez pas, vous pouvez profiter de la simplicité d’un autre logiciel, tout en appelant les fonctions de R à partir de ce logiciel comme je l’ai décrit ici.

Si vous êtes déjà un utilisateur de R et je suis passé à coté d ‘une de vos bêtes noires, listez les dans la section des commentaires ci-dessous s’il vous plaît.(NdT : lien ici)


À propos de l'auteur

Vincent Guyader

Vincent Guyader

Codeur fou, formateur et expert logiciel R


Commentaires

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *


À lire également

Nos formations Certifiantes à R sont finançables à 100% via le CPF

Nos formations disponibles via moncompteformation.gouv.fr permettent de délivrer des Certificats reconnues par l’état, enregistrées au répertoire spécifique de France Compétences. 3 niveaux de certifications existent :

Contactez-nous pour en savoir plus.

Calendrier

04/06/2024

14/05/2024

14/05/2024