Académique Documents
Professionnel Documents
Culture Documents
R et Splus
Emmanuelle Comets
Introduction 7
1 Premiers pas en S 9
1.1 Présentation du langage S . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.1.1 Pourquoi utiliser S . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.1.2 R et Splus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.2 Présentation du système . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.2.1 Démarrer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.2.2 Quitter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.3 Eléments importants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.3.1 Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.3.2 Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.4 Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.4.1 Manuel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.4.2 Autres sources d’aide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.5 Organiser son travail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.5.1 Gestion des objets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.5.2 Gestion des projets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2 Données et variables 17
2.1 Variables de S . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.1.1 Types de variables et conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.1.2 Créer des variables : l’opérateur d’affectation . . . . . . . . . . . . . . . . . . . . . . . . 18
2.1.3 Utilisation de la fenêtre de commande comme une calculette . . . . . . . . . . . . . . . 18
2.1.4 Expressions logiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.2 Vecteurs et matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.2.1 Outils de création d’un vecteur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.2.2 Manipulation de vecteurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.2.3 Création d’une matrice ou d’un tableau . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
3
4 TABLE DES MATIÈRES
3 Graphes 43
3.1 Fonctions graphiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
3.1.1 Créer et modifier un graphe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
3.1.2 Types de graphes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
3.1.3 Interpolation et lissage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
3.2 Environnement graphique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
3.2.1 Principales options graphiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
3.2.2 Sauver un graphe dans un fichier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
4 Analyses statistiques 57
4.1 Statistiques descriptives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
4.1.1 Fonctions de base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
4.1.2 Distributions statistiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
4.1.3 Tests statistiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
4.2 La régression linéaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
4.2.1 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
4.2.2 Modèle statistique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
4.2.3 Résultats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
4.2.4 Graphes de diagnostic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
4.2.5 Evaluation et modification du modèle statistique . . . . . . . . . . . . . . . . . . . . . 67
4.2.6 Autres fonctions de régression . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
4.3 Quelques autres analyses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
TABLE DES MATIÈRES 5
5 Scripts et fonctions 77
5.1 Scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
5.1.1 Ecriture de scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
5.1.2 Exécution de scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
5.1.3 Note concernant les chemins sous Windows . . . . . . . . . . . . . . . . . . . . . . . . 79
5.2 Tests et boucles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
5.2.1 Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
5.2.2 Boucles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
5.3 Fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
5.3.1 Ecriture de fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
5.3.2 Arguments et résultats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
5.3.3 Méthodes et fonctions : la programmation orientée objet . . . . . . . . . . . . . . . . . 86
5.3.4 Autres fonctions utiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
Bibliographie 104
Index 106
Introduction
Ce cours contient toutes les bases nécessaires pour débuter le travail en S. Il peut être utilisé comme
mini-guide de référence décrivant les principales commandes.
Ce cours comprend 6 chapitres, ainsi qu’un index à la fin du manuel reprenant les fonctions expliquées et
les mots-clés, par ordre alphabétique :
Le chapitre 1 contient une introduction au système, avec la façon d’appeler le programme et d’organiser
une session de travail. La seule section à ne pas rater est 1.4.1 qui décrit le système d’aide de Splus et
R.
Le chapitre 2 rentre dans le vif du sujet, avec les types de données et de variables utilisées, avec tout ce
que vous voulez savoir sur la façon de les écrire, de les manipuler et de les modifier.
Le chapitre 3 traite des graphiques, en expliquant les différents types de graphiques possibles et leurs
options.
Le chapitre 4 explique comment faire une analyse simple en S. Nous aborderons la régression linéaire en
montrant comment mettre en forme les données, comment écrire le modèle, comment interpréter
les résultats et comment utiliser l’objet résultat de l’analyse pour tracer des graphiques permettant
d’effectuer des diagnostics sur notre modèle. Nous parlerons ensuite d’autres types de modèles.
Le chapitre 5 est consacré aux scripts et aux fonctions, et nous y apprendrons comment les définir et les
utiliser. C’est le début de la programmation en S.
Le chapitre 6 abordera la question des extensions de S, en montrant comment utiliser des librairies. Nous
utiliserons la librairie nlme comme exemple. Nous verrons aussi comment créer des librairies parta-
gées constituées de programmes C compilés.
Nous supposerons dans la suite que l’on dispose de R ou Splus sur sa machine, sous un système d’ex-
ploitation Linux ou Windows (je n’ai jamais essayé sur Macintosh mais je présume que ce doit être très
proche de Windows). Hormis les différences visuelles dues à la présence d’une fenêtre graphique sous
Windows (voir section 1.2), la distinction entre les systèmes d’exploitation est en général faible. La pre-
mière différence notable concerne les chemins des fichiers en lecture ou écriture (section 5.1.3). La deuxième
concerne l’utilisation de librairies et la compilation de fonctions écrites dans d’autres langages pour être
interfacées avec S (section 6.6).
7
8 INTRODUCTION
A partir du chapitre 2, les exemples que je donnerai seront tous tirés de R et je ferai référence à R
plutôt qu’au langage S ou à Splus. J’essaierai de documenter toutes les différences entre les deux logiciels
R et Splus que nous pourrons rencontrer au cours de ces exemples. Si malgré cela vous avez un message
d’erreur sous Splus en tentant de recopier une de ces commandes, merci de m’en avertir car j’ai dû en
laisser passer une !
Remerciements
Pour préparer ce cours, j’ai utilisé les ouvrages de référence de Splus [1] et le manuel et la documenta-
tion intégrée de R (disponible sous forme de pages HTML). J’ai également abondamment utilisé un certain
nombre de tutoriels ou de guides trouvés sur Internet [2, 5] dont je n’ai pas toujours gardé toutes les réfé-
rences. Merci à tous ces cours disponibles et à ceux qui les ont préparés et mis à disposition !
Merci également à Denis à qui je dois l’interface entre des programmes C et R et qui m’a laissée inclure
dans ce cours le chapitre portant sur la compilation de librairies partagées.
Avertissement
J’utilise R pour Linux depuis des années, après avoir commencé par Splus. Ce guide a été écrit à partir
de mon expérience de ces deux logiciels. La plupart des commandes disponibles sous R sont également
utilisables sous Splus, et j’ai essayé de tester les exemples donnés sous Splus et sous R quand j’avais des
doutes quant à la portabilité du code. Si malgré tout une des commandes proposée s’avérait ne pas marcher
exactement comme prévu et donnait un message d’erreur, lire la documentation du logiciel sous lequel on
travaille permet en général de résoudre le problème. Le plus souvent, il ne s’agit que de changer la syntaxe
d’appel d’une fonction.
Chapitre 1
Premiers pas en S
Dans ce chapitre, nous verrons comment démarrer le logiciel, quels sont les éléments importants à
comprendre et à connaître. Nous proposerons également quelques pistes d’organisation pour prendre de
bonnes habitudes dès le départ...
S est un langage de programmation utilisé abondamment par les mathématiciens et les statisticiens,
bien que n’ayant pas spécifiquement été conçu pour les statistiques. S connaît deux déclinaisons, Splus
(Insightful) qui est un logiciel commercial disposant de nombreux modules spécialisés, et R qui est un
logiciel libre.
S est un langage de programmation interactif et facile à apprendre (surtout aidés par un guide comme
celui-ci). La manière d’appeler les différents objets est intuitive une fois qu’on a compris les règles de base.
Quelques raisons d’utiliser S :
• c’est un langage contenant un grand choix de techniques statistiques
• on peut faire des graphiques entièrement paramétrisables
– les graphes sont beaux (rien à voir avec ceux de SAS)
– tous les éléments sont paramétrisables (légendes, ajout de texte, échelles, limites des graphes)
– on peut superposer plusieurs courbes pour ajouter par exemple le résultat d’analyse de régression
• les graphes peuvent être exportés
– sous forme de fichiers postscript : ces fichiers sont visualisables et imprimables sous Linux (et sous
Windows avec ghostscript, un logiciel librement téléchargeable et installable) et ils peuvent être
intégrés à LATEX
– par copier-coller pour intégration dans des présentations Powerpoint ou dans des rapports (sous
Windows)
• S est un langage de programmation
9
10 Chapitre 1. Premiers pas en S
– il est facile de développer des fonctions, par exemple pour visualiser le résultat d’analyses réalisées
par un autre logiciel
– on peut automatiser le traitement des données pour un type de problème particulier
– on peut créer des bibliothèques de fonctions ou de programmes pour s’aider dans son travail
quotidien
– on peut mettre en place des simulations compliquées en utilisant la puissance de programmation
du langage
• il existe de nombreux modules et de nombreuses librairies spécialisées disponibles sur Internet
– de nombreux chercheurs ont développé leurs propres algorithmes sous S et les ont mis à disposi-
tion de la communauté scientifique
– cette technique assure une diffusion des méthodes statistiques mises au point
– la programmation modulaire permet d’utiliser des librairies pour faire des analyses statistiques
récemment publiées sans attendre l’intégration de nouvelles méthodes dans le logiciel
– si la mise en oeuvre n’existe pas encore, on peut aussi la programmer soi-même en S
• il est très facile d’interfacer S :
– avec d’autres langages de programmation comme le C ou le Fortran
– avec d’autres outils : on peut créer des interfaces Web par l’intermédiaire de CGI ou Perl
Pour toutes ces raisons, S fait partie des logiciels les plus utilisés.
1.1.2 R et Splus
Le langage S a été développé aux laboratoires de Bell par Rick Becker, John Chambers et Allan Wilks
dans les années 70.
Splus est la mise en oeuvre commerciale du langage S. Il a été développé par Bill Venables et David M.
Smith et c’est actuellement la société Insightful qui le commercialise.
R est un logiciel libre distribué sous licence GNU. Ses auteurs officiels sont Robert Gentleman et Ross
Ihaka (Statistics Department, University of Auckland, New-Zealand) mais la liste des collaborateurs de R
inclut des noms comme John Chambers, l’auteur du langage S ou Brian Ripley. Le manuel de R spécifie "R
is a computer language not entirely unlike the S language developed at AT&T Bell
Laboratories by Rick Becker, John Chambers and Allan Wilks" ce qui est pour le moins
un euphémisme.
Les deux logiciels correspondent en fait à deux mises en oeuvre du même langage. Certaines options de
programmation diffèrent, mais la philosophie du langage est la même. En pratique, R et Splus sont presque
interchangeables, et pour un utilisateur normal la plupart des commandes sont utilisées de la même façon
dans l’un ou l’autre des langages. Les deux logiciels sont disponibles sous différentes plateformes (Linux,
Unix, Macintosh ou Windows). J’essaierai dans ce cours de vous signaler les endroits (fonctions, arguments
ou autres) où les deux logiciels diffèrent, mais bien sûr c’est difficile d’être exhaustif. Donc si une fonction
ne marche pas tout à fait comme prévu, vérifiez la doc !
Il semble aussi d’après mon expérience personnelle et la rumeur publique que Splus soit plus lent que
R pour un certain nombre de calculs.
1.2 Présentation du système 11
1.2.1 Démarrer
Windows
Double-cliquer sur l’icône de démarrage ou cliquer sur le programme dans le menu Démarrer.
Linux
Lancer l’exécutable, en général R ou R<numéro de version> (le chemin est automatiquement ajouté au
$PATH à l’installation du logiciel).
1.2.2 Quitter
On utilise soit le menu déroulant (sous Windows) :
Menu File - Exit
soit la fenêtre de commande avec la commande q() :
> q("no")
ou
> q()
Save workspace image? [y/n/c]: n
1.3.1 Windows
Menus
Comme pour tous les logiciels Microsoft, la barre de menus déroulants permet d’utiliser une bonne
partie des capacités du logiciel.
Splus a la barre de menus la plus fournie, au point qu’on se demande si on n’est pas sous Excel. Celle
de R est plus sobre.
Fenêtre de commande
Explorateur d’objets
Cette fenêtre permet de visualiser tous les objets créés durant une session. L’onglet Propriétés associé
à chaque objet permet de visualiser les caractéristiques de l’objet (type de variable, noms des éléments qui
le composent...) et de les modifier.
12 Chapitre 1. Premiers pas en S
On peut ouvrir plusieurs fenêtres permettant d’écrire des scripts (fichiers contenant un ensemble de
commandes Splus qui peuvent être exécutées comme un programme, voir section 5.1). Une fenêtre s’ouvre
automatiquement lorsque l’on ouvre un fichier script existant :
Menu File - Open
On peut aussi créer une nouvelle fenêtre pour écrire un script :
Menu File - New Script File
Fenêtres graphiques
Une fenêtre graphique s’ouvre lorsqu’un graphe est créé. Un graphe est un objet qui dispose d’un
certain nombre de propriétés. Il peut donc être modifié après sa création, en cliquant sur différents éléments
du graphe.
1.3.2 Linux
1.4 Documentation
1.4.1 Manuel
L’aide en ligne est particulièrement bien faite. Elle est en général claire et lisible (que tout ceux qui ont
eu l’impression d’être bêtes en lisant la doc de SAS se rassurent) et comprend des exemples qui aident à
comprendre le fonctionnement des instructions. L’appel à l’aide sur une commande, par exemple la fonc-
tion mean() se fait par la commande help() :
> help(mean)
Le logiciel affiche une page (déroulante sous Linux, dans une fenêtre à part pour Windows qui mérite
bien son pluriel) contenant l’aide disponible. Elle comprend 6 sections :
Arguments : les paramètres qu’il est nécessaire de donner à la fonction, avec la description de leur usage ;
certains paramètres sont des options, qui peuvent avoir une valeur par défaut (nous y reviendrons
dans le chapitre consacré à la fabrication des fonctions 5.3).
Détails : des remarques particulières concernant l’usage de la fonction, comme l’algorithme ou la méthode
statistiques utilisés pour programmer la fonction.
Résultat : le résultat est le plus souvent un objet dont les caractéristiques (attributs) principaux sont décrits
ici. Les fonctions applicables à l’objet peuvent également être données ici.
Exemples : la section la plus importante car elle permet de bien comprendre la syntaxe de la fonction.
Quand on ne connaît pas exactement le nom de la fonction qui nous intéresse (cas typique : on l’a oublié
mais on sait que ça ressemble à...) on peut tenter une recherche dans les mots-clés. Pour cela on utilise la
commande help.search(""). Par exemple :
> help.search("mean")
Note : Cette fonction n’existe pas sous Splus mais on peut utiliser le menu "Aide" et faire une recherche par mot-clé
ou sur le nom de la fonction.
Livres
Sites Internet
Tutoriels
La Toile regorge de sites dédiés à tel ou tel aspect des logiciels R et Splus. Certains proposent des
transparents d’introduction, d’autres des exemples d’application, certains encore des documentations aussi
épaisses que le manuel d’origine. Vous en trouverez par exemple à :
• http ://pbil.univ-lyon1.fr/Splus/splus.html
• http ://statwww.epfl.ch/splus/
Outre l’explorateur d’objets existant sous Windows, on peut afficher la liste des objets créés lors d’une
session dans la fenêtre de commande par la commande ls().
> ls()
Parmi les options, ls("pat="moi") donne la liste des objets ayant "moi" dans leur nom, tandis que ls("pat="∧ moi")
donne la liste de ceux commençant par "moi".
Les objets peuvent être supprimés en utilisant la fonction rm().
> rm()
L’ensemble des objets créés pendant la session peut être sauvegardé pour une utilisation ultérieure
lorsque l’on quitte le programme. Il suffit d’utiliser l’option "yes" de la fonction q(), comme suit :
> q("yes")
ou
> q()
Save workspace image? [y/n/c]: y
Ceci a pour effet de sauvegarder un fichier (.RData sous R) qui contient toutes les variables créées. Au
lancement suivant de R, le logiciel lit ce fichier et toutes les variables précédemment utilisées redeviennent
disponibles.
Note : Bien que pratique, cette option a tendance à créer de gros fichiers dans chaque sous-répertoire de travail qui
peuvent assez rapidement encombrer le disque dur. C’est le cas notamment dès qu’on travaille sur de grosses
matrices ou que l’on lit de gros fichiers. Il peut donc être plus souhaitable de travailler plutôt par scripts (voir
section 5.1).
Les fichiers créés par R ou Splus peuvent être effacés du disque sans dommages une fois sortis du
programme, quand on a fini de travailler sur un thème par exemple.
Sous R, la commande save.image() permet de sauvegarder l’état d’une session sans quitter le pro-
gramme.
> save.image()
>
Répertoire de travail
Sous Linux, il suffit de lancer R ou Splus dans le répertoire désiré pour que celui-ci devienne le réper-
toire de travail. Deux fichiers spéciaux appelés .RData et .Rhistory (sous R) sont créés pour que le logiciel
puisse travailler avec. Si on sort de la session en sauvant l’image, ces fichiers sont sauvegardés sur le disque
et chargés automatiquement au début de la session suivante lancée dans le même répertoire.
Chaque répertoire de travail contient un .RData différent une fois que la session a été sauvée. Ceci
permet de compartimenter facilement différentes analyses.
Sous Windows, on peut utiliser les menus pour spécifier un répertoire de travail :
Menu Options - General Settings - Onglet Startup
et cocher "Prompt for project folder". Au prochain démarrage de Splus, le programme demande dans
quel répertoire on veut travailler. On peut alors rentrer le répertoire désiré. Si on travaille longtemps dans
le même répertoire, on peut choisir de décocher l’option "Prompt for project folder" pour travailler toujours
dans le même, et le jour où on a envie de changer repasser par le menu Options.
16 Chapitre 1. Premiers pas en S
On peut aussi créer une icône spéciale pour chaque projet, en utilisant des raccourcis. En créant un
raccourci correspondant à l’exécutable R, puis en cliquant dessus avec le bouton droit de la souris et en
choisissant l’option "Propriétés", on obtient la fenêtre suivante :
Pour automatiser la création de répertoire, on peut donc modifier les propriétés de l’objet comme suit :
1. modifier éventuellement le nom du raccourci pour le rendre plus évocateur (par exemple "R projet
bootstrap")
2. changer le chemin indiqué dans "Démarrer dans" pour qu’il indique le chemin complet du répertoire
de travail (après avoir cliqué avec le bouton droit de la souris et sélectionner l’option "Propriétés")
Chapitre 2
Données et variables
A partir de ce chapitre, nous ne nous intéresserons plus qu’à la fenêtre de commande. Toutes les com-
mandes étant accessibles en ligne de commande, il est préférable d’être capable de comprendre et confi-
gurer les commandes dont on a besoin. Cela permettra également de travailler de façon non interactive.
Enfin, toute la puissance de R apparaît lorsque l’on veut écrire des fonctions automatisées, ne serait-ce que
lorsque l’on veut faire plusieurs fois le même graphique sur plusieurs fichiers de données différents.
Rappel : à partir de ce chapitre nous nous placerons par défaut sous R.
La section la plus importante de ce chapitre concerne la manipulation des vecteurs (section 2.2.2). Si
vous avez compris comment ça fonctionne, l’utilisation de R deviendra très vite extrêmement intuitive...et
vous deviendrez très vite extrêmement efficaces !
2.1 Variables de S
Les noms des variables obéissent à certaines conventions. Elles doivent commencer par une lettre, et
peuvent comprendre des points. En revanche elles ne peuvent pas contenir un caractère "_" car celui-ci est
utilisé par l’opérateur d’affectation dans les anciennes versions de R (voir section suivante). De même, le
caractère "$" est utilisé pour désigner les éléments d’une liste donc on ne peut pas l’utiliser à l’intérieur
d’un nom.
17
18 Chapitre 2. Données et variables
Certains noms ne sont pas autorisés car ils correspondent à des constantes ou à des fonctions utilisées
par le logiciel. En revanche, il est possible (quoiqu’évidemment pas du tout conseillé) de définir une va-
riable toto alors qu’on a déjà une fonction toto(). Mais R génère alors des messages d’alerte chaque fois
qu’on l’utilise, ce qui est vite pénible. La table 2.1 montre des noms de variables acceptables ou non.
x, Y, z1 Noms acceptables
x, Y, z1, toto.dat Noms acceptables
1Z Interdit : nom commençant par un chiffre
c, TRUE, pi Interdit : nom réservé par le programme
L’opérateur d’affection est la flèche inverse "←" constitué du caractère plus petit que "<" et du signe
moins "-". Par exemple, pour créer une variable en lui affectant la valeur 3, on écrit :
> x<-3
R ne connaît que les variables qu’on lui a explicitement créées. Ainsi, si on appelle une variable incon-
nue, on a un message d’erreur.
> y
Error: Object "y" not found
> a<-b<-6
Après cette opération, a et b ont été créées et elles ont toutes les deux la valeur 6.
Note sur les autres opérateurs d’affectation : on peut également utiliser les deux opérateurs suivants "_" et "=". Tou-
tefois, en plus d’être illisible l’opérateur "_" est en passe de devenir obsolète et son utilisation dans les dernières
versions de R vous vaudra un message d’alerte à chaque fois. Pour ce qui est de "=", son usage est un peu dé-
conseillé dans la mesure où il est facile de le confondre avec le double égal "==" qui nous servira à faire des
tests d’égalité.
> x
[1] 3
Munis de ces premiers outils nous pouvons utiliser R comme une calculatrice et lui faire effectuer des
opérations.
2.1 Variables de S 19
> 1-pi+exp(1.7)
[1] 3.332355
> x<-1-pi+exp(1.7)
> x
[1] 3.332355
> x**2
[1] 11.10459
> x^2
[1] 11.10459
Les fonctions mathématiques standards existent et vous en trouverez quelques-unes dans la table 2.2.
> x<-3;y<-x**2;y
[1] 9
Les expressions logiques servent à effectuer des tests. Les opérateurs de comparaison (dits aussi boo-
léens) peuvent être appliqués à des variables numériques. Le résultat est un booléen VRAI/FAUX.
• opérateurs de comparaison
– plus petit que : <, <= pour < et ≤
– plus grand que : >, >= pour > et ≥
– égalité : == (double égal)
– différence : !=
• combinaison de tests
– et logique : &
– ou logique : |
20 Chapitre 2. Données et variables
– et séquentiel : && (le premier test est réalisé ; si son résultat est T ("true" : vrai), on continue, sinon
on n’effectue pas les tests suivants)
– ou séquentiel : ||
Ils peuvent aussi être appliqués à d’autres variables, notamment des variables de type chaînes de caractères
ou des listes, mais le résultat est moins immédiat à interpréter.
Note 1 : quand on travaille avec des variables numériques, le test d’égalité == peut échouer pour des problèmes
d’arrondi (la représentation d’un nombre dans la mémoire de l’ordinateur est finie car elle utilise un nombre
fini d’octets, et lors de la manipulation et du stockage des nombres des erreurs dites d’arrondi ("rounding
errors") peuvent survenir). Il est préférable d’utiliser un test du type abs(x-y)<epsilon avec epsilon petit (ex :
10−6 ).
Note 2 : attention également à l’usage des tests d’égalité en cas de test sur plusieurs éléments d’un vecteur Par défaut
le résultat de la comparaison sur le premier élément seulement est considéré. Il vaut mieux dans ce cas utiliser
la fonction all.equal() (voir doc).
> myvec<-c(3,4.1,8.6)
> myvec
[1] 3.0 4.1 8.6
> vec<-seq(0,10,2)
> vec
[1] 0 2 4 6 8 10
> vec<-4.5:8.5
> vec
[1] 4.5 5.5 6.5 7.5 8.5
> vec<-1:3
> vec
2.2 Vecteurs et matrices 21
[1] 1 2 3
> rep(vec,times=2)
[1] 1 2 3 1 2 3
> rep(vec,2)
[1] 1 2 3 1 2 3
> rep(vec,each=3)
[1] 1 1 1 2 2 2 3 3 3
> rep(vec,times=2,each=3)
[1] 1 1 1 2 2 2 3 3 3 1 1 1 2 2 2 3 3 3
On peut manipuler des vecteurs exactement comme des variables. R comprend l’instruction vec+3
comme "ajoute à chaque élément de vec la valeur 3". De même, il comprend log(vec) comme "applique
à chaque élément de vec la fonction log()". Du coup, on peut créer un vecteur vec de 11 cases allant de 0.1
à 1 par :
> vec<-0:10/10
> vec
[1] 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
> vec<-seq(0,1,by=0.1)
On peut aussi lui appliquer des tests, toujours élément par élément :
> myvec<-c(3,-4,-2.3,exp(2))
> myvec
[1] 3.000000 -4.000000 -2.300000 7.389056
> myvec>0
[1] TRUE FALSE FALSE TRUE
Référencer un vecteur
> vec[2]
[1] 0.1
A la place de vec[2], on aurait pu utiliser une variable, par exemple la variable indice :
22 Chapitre 2. Données et variables
> indice<-2
> vec[indice]
[1] 0.1
On peut aussi vouloir sélectionner plusieurs éléments de vec, par exemple les éléments 3, 6 et 7 :
> vec[c(3,6,7)]
[1] 0.2 0.5 0.6
Arrêtons-nous un instant : en fait, nous avons demandé à vec les éléments dont l’indice était 3, 6 et 7,
c’est-à-dire que nous avons donné à vec[] un vecteur d’entiers c(3,6,7). R a alors sélectionné les indices
correspondant et nous les a affichés.
Note : Prenez bonne note de ce fonctionnement car nous allons nous en servir constamment ! C’est grâce à lui que
nous allons pouvoir sélectionner facilement des sous-ensembles parmi un grand tableau de données.
Si on veut les éléments 4 à 7 par exemple, on peut aussi utiliser une séquence avec " :" :
> vec[4:7]
[1] 0.3 0.4 0.5 0.6
Ceci est une formulation très concise, très pratique, et qu’on utilise tout le temps. Par exemple, quand on a
créé un vecteur ou une matrice par une série d’opérations et de tests, on peut vouloir visualiser les premiers
éléments pour vérifier qu’on n’a pas fait d’erreurs :
> vec[1:5]
[1] 0.0 0.1 0.2 0.3 0.4
Une façon équivalente de demander les éléments 3, 6 et 7 aurait été d’utiliser un vecteur de booléens,
valant TRUE (T) pour les éléments qu’on veut afficher et FALSE (F) pour les autres.
> vec[c(F,F,T,F,F,T,T,F,F,F)]
[1] 0.2 0.5 0.6
Ceci peut s’étendre de façon très intuitive. Supposons maintenant qu’on veuille en extraire les éléments
strictement supérieurs à 0.3 de vec. On sait que le test vec>0.3 nous donnera un booléen de la même taille
que vec, et que vec[vecteur de booléens] affiche tous les éléments pour lequel le vecteur de booléen vaut
T. Donc il suffit d’écrire :
> vec[vec>0.3]
[1] 0.4 0.5 0.6 0.7 0.8 0.9 1.0
> vec[vec>0.3]<-vec[vec>0.3]+1
> vec
[1] 0.0 0.1 0.2 0.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0
Ici, on a ajouté 1 à tous les éléments qui étaient supérieurs à 0.3 sans toucher aux autres, et on a changé le
vecteur vec dans la bagarre.
2.2 Vecteurs et matrices 23
On peut utiliser la forme vec[-c()]. Par exemple, pour afficher vec sans les éléments d’indices 3, 6 et 7 :
> vec[-c(3,6,7)]
[1] 0.0 0.1 0.3 1.4 1.7 1.8 1.9 2.0
On peut aussi utiliser des tests pour exclure des éléments, en utilisant le test ! qui signifie "is not" et
transforme un booléen en son inverse :
> vec>0.3
[1] FALSE FALSE FALSE FALSE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
> !(vec>0.3)
[1] TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
> vec[!(vec>0.3)]
[1] 0.0 0.1 0.2 0.3
L’instruction signifie "enlèves les éléments supérieurs à 0.3". La signification et l’utilisation des différents
tests seront détaillées dans le chapitre sur les fonctions (section 5.3).
On peut créer une matrice à l’aide de la fonction matrix(x,options,byrow=T/F). x est un vecteur qui
est mis sous la forme d’une matrice d’un nombre spécifié de lignes et/ou de colonnes. Si l’option byrow
vaut TRUE, le vecteur est placé ligne par ligne dans la matrice sinon il est placé colonne par colonne
(comportement par défaut).
> vec<-1:20
> vec
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
> matrix(vec,ncol=4,byrow=F)
[,1] [,2] [,3] [,4]
[1,] 1 6 11 16
[2,] 2 7 12 17
[3,] 3 8 13 18
[4,] 4 9 14 19
[5,] 5 10 15 20
> matrix(vec,ncol=4,byrow=T)
[,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 5 6 7 8
[3,] 9 10 11 12
[4,] 13 14 15 16
[5,] 17 18 19 20
On peut aussi créer une matrice remplie d’un nombre quelconque en utilisant les options de matrix() :
24 Chapitre 2. Données et variables
> matrix(ncol=2,nrow=2)
[,1] [,2]
[1,] NA NA
[2,] NA NA
> matrix(data=0,ncol=2,nrow=2)
[,1] [,2]
[1,] 0 0
[2,] 0 0
> vec1<-c(1:3)
> mat1<-matrix(4:12,ncol=3,byrow=T)
> vec1
[1] 1 2 3
> mat1
[,1] [,2] [,3]
[1,] 4 5 6
[2,] 7 8 9
[3,] 10 11 12
Ces instructions sont très utiles pour créer des tableaux de données à partir de multiples fichiers issus de
bases de données. En revanche, leur exécution est assez lente lorsque la taille des matrices augmente, donc
il vaut mieux éviter leur utilisation à l’intérieur de boucles ou de programmes trop importants.
Par extension, on peut créer un tableau ayant plus que 2 dimensions. C’est le but de l’instruction array().
Comme avec matrix(), on peut créer un tableau à partir d’un vecteur, ou créer un tableau ne contenant par
exemple que des 1 :
> array(data=1,dim=c(2,3))
[,1] [,2] [,3]
[1,] 1 1 1
[2,] 1 1 1
On peut aussi donner des noms aux lignes et aux colonnes, avec l’option dimnames :
> mytab<-array(data=1,dim=c(2,3),dimnames=list(c("R1","R2"),c("C1","C2","C3")))
2.2 Vecteurs et matrices 25
> mytab
C1 C2 C3
R1 1 1 1
R2 1 1 1
dimnames est une option valide également pour les matrices. Elle permet de donner des noms à chaque
rangée, colonne, ou autre dimension du tableau. C’est un argument très utile quand on travaille sur des
bases de données pour repérer la signification des colonnes.
Note : Au passage, l’argument de l’option dimnames est un objet de type liste (voir plus loin dans ce chapitre). Celle-
ci est simple, elle est constituée d’une liste de 2 vecteurs de dimensions spécifiées par l’option dim qui donne
les dimensions du tableau.
> mymat<-matrix(vec,ncol=4,byrow=T)
> mymat[2,3]
[1] 7
On fait référence à la ligne i de la matrice mymat par mymat[i,], et à la colonne j par mymat[,j] :
> mymat[2,]
[1] 5 6 7 8
> mymat[,2]
[1] 2 6 10 14 18
De même que précédemment avec les vecteurs, on peut afficher les premières lignes pour vérifier par
exemple que les données ont bien été rangées dans la matrice dans l’ordre voulu :
> mymat[1:3,]
[,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 5 6 7 8
[3,] 9 10 11 12
Par défaut comme on l’a vu, l’opérateur "+" effectue des additions éléments par éléments. C’est la même
chose pour les 4 opérateurs usuels "+ - × ÷" (ou pour des opérations utilisant des fonctions).
Pour obtenir une multiplication matricielle, et en supposant que a et b soient des matrices de taille
respectivement m×n et n×l, le produit matriciel de a et b s’obtient par a%*%b :
> a<-matrix(1:6,ncol=3,byrow=T)
> b<-matrix(1:12,ncol=4,byrow=T)
> a
26 Chapitre 2. Données et variables
Il existe aussi un certain nombre de fonctions applicables aux matrices, résumées dans la table 2.3.
Note 1 : Sous Splus, les options de det() sont différentes (non compatibles).
Note 2 : Il existe également une librairie spécialisée dans l’algèbre linéaire, appelée Matrix. Elle possède entre autres
des fonctions de décomposition LU, de test d’orthonormalité, ou de calcul de la norme. Voir section 6.6 pour
plus d’informations sur les librairies et leur utilisation.
Les fonctions décrites dans la table 2.4 sont très utiles pour travailler sur des jeux de données.
La fonction length() sert à donner le nombre d’éléments d’un objet, tandis que dim() donne les dimen-
sions (nombre de colonnes et de lignes pour une matrice par exemple).
Les fonctions de tri sont un peu plus compliquées à utiliser, mais je vais essayer de vous donner un
aperçu de leur usage. Commençons par la plus simple, sort(), qui permet de trier un vecteur. Par exemple :
2.2 Vecteurs et matrices 27
TAB . 2.4 : Fonctions applicables aux variables numériques, vecteurs, matrices et tableaux.
> vecatrier<-c(3,-4,8,1,-7,0,3)
> sort(vecatrier)
[1] -7 -4 0 1 3 3 8
Notez que vecatrier contient 2 fois la valeur 3. On peut utiliser la fonction unique() pour se débarrasser des
réplications :
> factor(vecatrier)
[1] 3 -4 8 1 -7 0 3
Levels: -7 -4 0 1 3 8
La fonction order() donne la permutation qu’il faudrait utiliser sur les éléments pour trier le vecteur.
> order(vecatrier)
[1] 5 2 6 4 1 7 3
Donc logiquement, si je lui demande les éléments de vecatrier dans l’ordre donné par order(vecatrier), il va
me trier les éléments comme l’aurait fait la fonction sort() :
> vecatrier[order(vecatrier)]
[1] -7 -4 0 1 3 3 8
C’est bien, on a réinventé la roue. Enfin pas tout à fait ! ! ! C’est bien grâce à la fonction order() qu’on va
pouvoir faire des opérations de tri beaucoup plus compliquées sur des matrices, ou trier un vecteur selon
l’ordre d’un deuxième, etc... Un exemple d’application : supposons que vecatrier soit en réalité la différence
entre le résultat d’un test au temps t et le résultat au temps zéro pour une série de souches virales qu’on va
appeler souches. souches[order(vecatrier)] va nous permettre de trier les noms des souches en fonction de
la différence vecatrier :
>souches<-c("C1","C2","C3","C4","C5","C6","C7")
>souches[order(vecatrier)]
[1] "C5" "C2" "C6" "C4" "C1" "C7" "C3"
28 Chapitre 2. Données et variables
Tout ça en une seule ligne de commande ! Cette fonction va nous être extrêmement utile pour ordonner
des matrices suivant l’ordre d’une de ses colonnes. On peut utiliser order() sur plusieurs vecteurs à la fois,
donc imaginer de trier une matrice d’abord sur l’ordre de sa première colonne (des noms de patients) puis
sur l’ordre de sa deuxième colonne (les temps des visites), etc..., pour au final avoir une matrice contenant
chaque patient avec toutes ses visites dans l’ordre chronologique...
Enfin, la fonction rank() donne les rangs (le numéro d’ordre) dans l’échantillon :
> rank(vecatrier)
[1] 5.5 2.0 7.0 4.0 1.0 3.0 5.5
Lorsqu’il y a des valeurs répétées comme ici, le rang correspond à la moyenne des rangs.
On utilise la fonction factor() pour transformer des variables numériques (entières ou continues) en des
variables catégorielles :
> unique(sort(vecatrier))
[1] -7 -4 0 1 3 8
> vec<-1:20
> matrix(vec,ncol=6,byrow=T)
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 2 3 4 5 6
[2,] 7 8 9 10 11 12
[3,] 13 14 15 16 17 18
[4,] 19 20 1 2 3 4
Warning message:
Replacement length not a multiple of the elements to replace in matrix(...)
R nous dit qu’il a essayé de faire rentrer vec (un vecteur à 20 éléments) dans une matrice à 6 colonnes
(contenant donc un nombre d’éléments qui sera multiple de 6), mais que ça n’a pas marché (20 n’étant pas
un multiple de 6). Il a donc commencé par faire rentrer vec une fois, puis comme il restait des cases vides
(les 4 dernières de la ligne 4), il a repris vec et recommencé et puis évidemment il s’est arrêté au bout de 4
éléments, en affichant le message d’erreur.
Cette caractéristique de fonctionnement est typique de R et on peut l’appeler "règle du recyclage" : si
on tente par exemple d’additionner 2 vecteurs qui ne sont pas de la même taille, R prend le plus petit et
le répète autant de fois qu’il faut pour rentrer dans le plus grand, puis ajoute ce vecteur répliqué élément
par élément au plus grand. Si le plus grand est multiple du premier, il n’y a pas de message d’erreur, par
contre si ça dépasse, il le signale.
Un exemple :
2.3 Quelques points importants au sujet des variables 29
> a<-1:4
> b<-1:8
> a
[1] 1 2 3 4
> b
[1] 1 2 3 4 5 6 7 8
> a+b
[1] 2 4 6 8 6 8 10 12
> rep(a,2)+b
[1] 2 4 6 8 6 8 10 12
a est de taille 4, b est de taille 8, donc R crée un vecteur rep(a,2) de taille 8 et l’ajoute à b. Il n’y a pas de
message d’erreur car 8 est multiple de 4.
Note 1 : C’est d’ailleurs par la règle du recyclage qu’on comprend une instruction du type vec+3. On répète le chiffre
3 autant de fois qu’il y a d’éléments dans vec puis on l’ajoute élément par élément à vec.
Note 2 : L’unité de base de R est le vecteur. La règle du recyclage fonctionne également si on additionnait une matrice
avec un vecteur plus petit. R commence par convertir la matrice en un vecteur, applique la règle du recyclage,
fait le calcul, et remet le résultat dans la forme de la matrice. En revanche ça ne marche pas si on veut ajouter
deux matrices a et b de tailles inégales (il ne sait pas dans quel sens les traiter).
> a<-1:4
> b<-matrix(1:16,ncol=4,byrow=T)
> b
[,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 5 6 7 8
[3,] 9 10 11 12
[4,] 13 14 15 16
> a+b
[,1] [,2] [,3] [,4]
[1,] 2 3 4 5
[2,] 7 8 9 10
[3,] 12 13 14 15
[4,] 17 18 19 20
> miss<-0/0
> miss
[1] NaN
30 Chapitre 2. Données et variables
La façon "propre" de tester la présence de valeurs manquantes est d’utiliser la fonction is.na(). Cette
fonction peut s’appliquer à un vecteur, et teste alors élément par élément :
> miss<-c(miss,1:5)
> miss
[1] NaN 1 2 3 4 5
> is.na(miss)
[1] TRUE FALSE FALSE FALSE FALSE FALSE
Pour exclure les valeurs manquantes, on peut donc utiliser !is.na() (qui se lit "not is.na=T") :
> nomiss<-miss[!is.na(miss)]
> nomiss
[1] 1 2 3 4 5
Si on travaille avec une matrice, il faut tester colonne par colonne ou rangée par rangée :
> matmis<-cbind(c(1,6,NA,4),c(NA,5,2,3),1:4)
> matmis
miss
[1,] 1 NA 1
[2,] 6 5 2
[3,] NA 2 3
[4,] 4 3 4
> matmis[!is.na(matmis[,1]) & !is.na(matmis[,2]),]
miss
[1,] 6 5 2
[2,] 4 3 4
2.3.3 Affichage
Taper le nom d’une variable et appuyer sur "Enter" affiche le contenu de la variable de manière impli-
cite. Pour écrire quelque chose à l’écran de façon explicite on utilise la fonction cat().
> cat(matmis)
1 6 NA 4 NA 5 2 3 1 2 3 4>
Cette fonction transforme comme on le voit la matrice matmis en un vecteur et affiche tous ces éléments.
On peut aussi rajouter du texte, et exiger un saut de ligne en rajoutant "\n" dans la commande.
Note : ceux qui font de la programmation en C ne seront pas dépaysés par "\n".
Une autre façon d’afficher quelque chose à l’écran est d’utiliser print(). print() est une méthode et non
une fonction, c’est-à-dire que le résultat dépend de l’objet auquel elle est appliquée (voir section 5.3.3). Sur
une matrice par exemple, elle garde la forme de la matrice (contrairement à cat()) :
2.4 Autres objets 31
> print(matmis)
miss
[1,] 1 NA 1
[2,] 6 5 2
[3,] NA 2 3
[4,] 4 3 4
En R les chaînes de caractères sont des variables comme les autres, à ceci près que pour les différencier
des noms des variables il faut entourer les chaînes de guillemets :
On peut donc comme pour des nombres en faire des vecteurs et appeler un élément du vecteur :
Contrairement au C, il est possible sous R de copier directement une chaîne dans une autre :
> vecstr2<-vecstr
> vecstr2
[1] "Ceci est une chaine" "Ceci est une autre chaine"
> LETTERS[1:7]
[1] "A" "B" "C" "D" "E" "F" "G"
> letters[20:26]
[1] "t" "u" "v" "w" "x" "y" "z"
> month.name[9]
[1] "September"
32 Chapitre 2. Données et variables
Une fonction très utile pour manipuler des chaînes de caractères est la fonction paste() (colle en anglais)
qui permet de concaténer plusieurs chaînes de caractères :
> paste("Ceci","est","une","chaine")
[1] "Ceci est une chaine"
Remarquez que par défaut, les chaînes collées sont séparées par un blanc. On peut changer ce comporte-
ment par l’option sep="" pour spécifier ce qui doit séparer les chaînes.
> paste("Ceci","est","une","chaine",sep="")
[1] "Ceciestunechaine"
> paste("Ceci","est","une","chaine",sep="/")
[1] "Ceci/est/une/chaine"
Si l’un des éléments contenu dans paste() est un vecteur, fidèle à la règle du recyclage, on obtiendra un
vecteur :
> paste("V",1:5,sep="")
[1] "V1" "V2" "V3" "V4" "V5"
Très pratique pour automatiquement créer des noms de colonne par exemple. Si on ne veut pas un vecteur,
mais que les chaînes créées se mettent bout à bout, on peut utiliser l’option collapse="".
Ici, on a collé toutes les chaînes créées dans une seule en les séparant par un blanc.
Les data.frame sont des objets ressemblant beaucoup à des tableaux, mais en plus flexibles. On les crée
avec la fonction data.frame(). On peut par exemple transformer notre matrice matmis de la section 2.2.3 en
un data.frame :
> data.frame(matmis)
miss V2 V3
1 1 NA 1
2 6 5 2
3 NA 2 3
4 4 3 4
On remarque que les colonnes ont maintenant des noms. Comme la matrice matmis avait été créée en
utilisant le vecteur miss comme première colonne, c’est ce nom qu’il garde pour la première colonne. Pour
les autres, par défaut elles s’appellent V1, V2, ... (dans Splus, matmis.1, matmis.2). On peut leur donner
d’autres noms par la fonction dimnames() :
2.4 Autres objets 33
L’utilisation de dimnames() fait appel aux objets de type liste que nous allons voir dans la section suivante
(2.4.3).
Manipulation de data.frame
On peut faire référence aux éléments des data.frame exactement comme pour les matrices par [i,j] :
> mydf[1,3]
[1] 1
On peut aussi utiliser le fait que les data.frame ont des noms pour leurs colonnes et utiliser ce nom. On
peut utiliser deux méthodes :
• avec la syntaxe nomdudataframe$nomdelacolonne
• avec nomdudataframe[,nomdelacolonne]
Exemple :
> mydf$col1
[1] 1 6 NA 4
> mydf[1,3]
[1] 1
> mydf[,"col1"]
[1] 1 6 NA 4
Un data.frame est un objet qui possède un certain nombre de caractéristiques. On peut accéder à ces
caractéristiques en utilisant la fonction attributes().
> attributes(mydf)
$names
[1] "col1" "col2" "col3"
$row.names
[1] "1" "2" "3" "4"
$class
[1] "data.frame"
> lescol<-attributes(mydf)$names
> lescol
[1] "col1" "col2" "col3"
> leslign<-attributes(mydf)$row.names
> leslign
[1] "1" "2" "3" "4"
D’autres fonctions applicables aux data.frame sont dim(), qui donne les dimensions, et names(), qui donnent
les noms des colonnes.
> dim(mydf)
[1] 4 3
> names(mydf)
[1] "col1" "col2" "col3"
Jusqu’à présent, pour faire référence à une colonne, nous avons utilisé le nom du data.frame.
> essai<-data.frame(patient=paste("Patient",1:3),poids=c(80,68,73),age=c(55,62,36))
> essai
patient poids age
1 Patient 1 80 55
2 Patient 2 68 62
3 Patient 3 73 36
> patient
Error: Object "patient" not found
> attach(essai)
> patient
[1] Patient 1 Patient 2 Patient 3
Levels: Patient 1 Patient 2 Patient 3
Attention : si on modifie patient, on ne modifie pas essai$patient ! Donc si on veut changer le data.frame, il faudra
quand même utiliser la notation essai$patient.
> detach(essai)
2.4 Autres objets 35
Création de listes
La liste est l’objet le plus flexible de R. Il s’agit simplement comme son nom l’indique d’une liste d’objets
quels qu’ils soient. On les crée par l’instruction list(). On peut faire une liste des courses à faire pour le soir
par exemple :
[[2]]
[1] "pommes" "Elstar" "2 kg"
$autres
[1] "produit vaisselle" "petit"
$budget
[1] 30
Chaque élément de la liste est de type différent, on a simplement mis bout à bout dans une structure un
certain nombre d’objets.
En reprenant l’exemple précédent, on pourrait avoir plusieurs data.frame représentant des essais cli-
niques essai1, essai2, essai3 et créer une liste avec ces trois essais :
>developpement.clinique<-list(essaiFrance=essai1,essaiUK=essai2,essaiUSA=essai3)
On peut aussi créer une liste avec l’instruction vector() et l’option mode="list". On donne alors la lon-
gueur de la liste :
>maliste<-vector(length=10,mode="list")
Manipulation de listes
Pour faire référence à l’élément i de la liste, on utilise la syntaxe nomdelaliste[[i]] (notez les 2 crochets
pour indiquer le numéro de l’élément dans la liste), ou bien nomdelaliste[i]. Pour faire référence à l’élément
j de l’élément i de la liste, on utilise la syntaxe nomdelaliste[[i]][j].
> courses[[1]]
[1] "carottes" "1 kg"
> courses[[2]][1]
[1] "pommes"
On peut aussi utiliser directement les noms de la liste si les éléments ont des noms :
36 Chapitre 2. Données et variables
> courses$budget
[1] 30
> courses$autres[1]
[1] "produit vaisselle"
Note : l’extension à d’autres types de données est immédiate. Supposons que l’élément nomdelaliste[[i]] soit une
matrice, on référencera son élément [j,k] par nomdelaliste[[i]][j,k].
Attention : quand on appelle une liste par la syntaxe nomdelaliste[i], on fait appel à une représentation
vectorielle de la liste, alors que la syntaxe nomdelaliste[[i]] fait appel à la représentation en liste. On utilise
ces deux syntaxes de façon différente. Si on veut afficher le ième élément de la liste, il est indifférent d’utiliser
l’une ou l’autre des formes. En revanche si on veut afficher plusieurs éléments de la liste, il faut utiliser la
représentation vectorielle sinon on a des résultats étranges :
> courses[1:2]
[[1]]
[1] "carottes" "1 kg"
[[2]]
[1] "pommes" "Elstar" "2 kg"
> courses[[1:2]]
[1] "1 kg"
Par contre si on veut remplir le ième élément de la liste par quelque chose qui ne soit pas un élément unique
(par exemple, un vecteur, ou une liste, ou une matrice), il faut utiliser la syntaxe liste :
>maliste[[1]]<-courses[[2]]
A cause de cette syntaxe, l’utilisation des listes est parfois un peu compliquée : on ne peut pas par
exemple créer une liste de n matrices et trouver la moyenne de l’élément [i,j] de toutes les matrices de
la liste de façon "simple" (comprendre : il m’a fallu quelques essais pour trouver !), alors qu’on peut le
faire avec un array. C’est néanmoins possible grâce à l’utilisation de fonctions comme tapply() après avoir
transformé la liste en un objet plus maniable. C’est le but de l’instruction unlist() qui collationne bout à bout
tous les éléments de la liste pour en faire un vecteur :
> unlist(courses)
Néanmoins malgré ces difficultés conceptuelles les listes sont un outil puissant et très flexible.
La fonction dimnames() que nous avons vue en section 2.4.2 renvoie comme résultat un objet de type
liste. Si on veut modifier le nom des rangées seules de la matrice matmis, on va travailler sur l’élément [[1]]
de dimnames(matmis) :
2.4 Autres objets 37
> dimnames(matmis)
[[1]]
NULL
[[2]]
[1] "col1" "col2" "col3"
> dimnames(matmis)[[1]]<-paste("row",1:4)
> matmis
col1 col2 col3
row 1 1 NA 1
row 2 6 5 2
row 3 NA 2 3
row 4 4 3 4
R attend pour dimnames(matmis)[[1]] un vecteur de taille égale au nombre des rangées, d’où notre construc-
tion d’un vecteur de noms de rangées.
> is.data.frame(matmis)
[1] FALSE
> as.data.frame(matmis)
miss V2 V3
1 1 NA 1
2 6 5 2
3 NA 2 3
4 4 3 4
> miss[1]>0
[1] TRUE
> as.integer(miss[1]>0)
[1] 1
C’est très utile pour compter automatiquement le nombre d’éléments positifs. Attention toutefois à la pré-
sence de valeurs manquantes (par défaut, une fonction comme sum() renvoie NA si le vecteur d’entrée
contient des valeurs manquantes) :
> sum(as.integer(miss>1))
38 Chapitre 2. Données et variables
[1] NA
> sum(as.integer(miss>1),na.rm=T)
[1] 2
Note : en réalité, R fait lui-même la conversion d’un booléen en un entier de façon automatique, donc on aurait pu
écrire directement :
> sum(miss>1,na.rm=T)
[1] 2
On a vu que la fonction apply() permet d’appliquer une fonction à chaque colonne ou ligne d’une
matrice. La fonction lapply() permet d’appliquer une fonction à chaque élément d’une liste.
Encore plus intéressant dans certaines situations car permettant de faire des choses très subtiles, la fonc-
tion tapply() permet d’appliquer une fonction à un ensemble quelconque (exemple : vecteur, tableau, liste)
en fonction d’une variable facteur (=comprenant un certain nombre de catégories ou niveau). Supposons
qu’on ait par exemple une liste de 3 matrices de taille 2×2, et qu’on veuille la somme de chaque élément
[i,j] à travers les 3 matrices.
On a commencé par définir une variable facteur qui, si elle était mise sous la même forme que xlist,
aurait valu 1 pour tous les éléments [1,1], 2 pour tous les éléments [2,1], etc... Puis on a demandé à tapply()
de faire la somme (sum) des éléments de xlist en les regroupant selon les catégories définies par xfac.
Comme tapply() travaille sur des tableaux et non sur des listes, on a d’abord transformé xlist en un vecteur
par unlist(). On peut vérifier sur la dernière ligne que l’ordre de xfac correspond bien à l’ordre des éléments
de xlist.
>dat<-scan("monfichier.dat")
Dans cette configuration, scan() lit les données contenues dans le fichier donné, et suppose que toutes les
données sont des réels (de type double). S’il y a une donnée qui n’est pas interprétable comme un nombre,
il y a erreur :
Les options de scan() sont trop nombreuses pour être énumérées ici, car on peut paramétrer le type de
données attendues, le nombre de lignes lues, etc... Citons seulement les plus intéressantes :
• skip=n : permet de sauter les n premières lignes du fichier ;
• nlines=n : lit n lignes du fichier (aussi nmax=n, n=n le nombre maximal de données ou de champs à
lire) ;
• what=type : type de données à lire (on peut choisir de lire des caractères par exemple) ;
• sep="" : valeurs séparant deux champs (utile pour lire des fichiers où c’est un point-virgule ou un
blanc qui sépare deux champs) ;
• na.strings="" ou na="" : codage pour les valeurs manquantes dans le fichier (seront transformés en
NA dans R).
Par exemple, pour lire 10 lignes dans le fichier, en sautant la première ligne, et avec des valeurs man-
quantes codées par un point, on écrira :
>dat<-scan("monfichier.dat",skip=1,nlines=10,na=".")
Une autre fonction est disponible pour lire des tables (fichiers dont toutes les lignes ont le même nombre
de champs). C’est la fonction read.table(). Parmi les options, on peut citer :
• skip=n : permet de sauter les n premières lignes du fichier ;
40 Chapitre 2. Données et variables
> data(quakes)
ouvre par exemple un fichier contenant des informations sur les tremblements de terre ayant eu lieu au
large des îles Fidji.
L’option package=nomdunelibrairie permet de savoir quels fichiers de données sont joints à une librai-
rie donnée (base pour les fonctions de base chargées à l’ouverture de R).
> data(package=base)
Rappel : sous Windows on a aussi l’option d’importer des données (menu Files) qui permet d’ajuster précisément le
type de données lues au type du fichier de données.
> matmis
col1 col2 col3
row 1 1 NA 1
row 2 6 5 2
row 3 NA 2 3
row 4 4 3 4
> write(t(matmis),ncol=3,file="toto.dat")
> system("more toto.dat ")
1 NA 1
6 5 2
NA 2 3
4 3 4
Attention, si on veut écrire la matrice telle qu’on la voit à l’écran il faut utiliser sa transposée t(matmis)
(parce que par défaut R travaille en colonnes).
En utilisant la fonction write.table(), les options à regarder sous R sont quote=T (s’il faut mettre des
guillemets autour de chaque élément), row.names=T et col.names=T (s’il faut écrire le nom des rangées et
des colonnes).
2.5 Fichiers de données 41
Note : Les options de la fonction write.table() sont différentes sous Splus. Sous R, par défaut les noms des lignes et
des colonnes sont écrits dans le fichier, et des guillemets sont mis autour de chaque élément, ce qui n’est pas le
cas sous Splus. De plus les options ont des noms différents.
42 Chapitre 2. Données et variables
Chapitre 3
Graphes
Dans ce chapitre nous allons voir comment créer des graphes de tous types pour représenter nos don-
nées ou nos résultats d’analyse. Nous verrons les options disponibles pour mettre plusieurs graphes sur
une seule feuille, pour modifier la disposition des graphes ou les éléments qui le composent.
Fonction plot()
L’instruction de base pour tracer des graphes est la fonction plot(). Dans sa forme la plus simple, il suffit
de lui donner deux vecteurs de même taille pour tracer le nuage de points correspondant à chaque élément
du premier vecteur contre l’élément correspondant du deuxième vecteur :
1.0
0.5
> x<-pi*c(0:200)/50
> y<-cos(x)
0.0
> plot(x,y)
y
−0.5
−1.0
0 2 4 6 8 10 12
On peut aussi donner à la fonction une matrice, et plot() fera alors un graphe de la première colonne en
axe des abscisses et de la deuxième colonne en axe des ordonnées :
> pmat<-matrix(c(x,y),ncol=2)
> plot(pmat)
43
44 Chapitre 3. Graphes
Options
Les options les plus importantes de la fonction plot() sont données dans le tableau 3.1 :
Les options les plus utilisées en pratique sont main, les options pour donner des titres et des limites
explicitement aux axes, et les options permettant de changer les symboles ou le type de ligne utilisées.
Jouer sur les limites des axes permet notamment de zoomer sur une région du graphe, et peut permettre
notamment d’obtenir des graphes plus précis sur une fenêtre de valeurs de x. Ici on pourrait par exemple
vouloir zoomer sur la région où cos(x) intersecte l’axe des abscisses.
Par défaut, R trace un graphe où la zone de tracé est entourée d’une boîte, et le point d’origine (0,0) est
décalé pour permettre au dessin d’être centré dans la zone de tracé. Il est possible de modifier ce compor-
tement par défaut en utilisant l’option axes=F pour ne pas tracer les axes standards, et de tracer les axes
dans un deuxième temps en utilisant la fonction axis(). On peut ainsi spécifier 1 axe des abscisse et un axe
des ordonnées se croisant au point d’origine (0,0).
3.1 Fonctions graphiques 45
Modifions notre graphe précédent pour l’adapter en ajoutant des légendes, en modifiant les limites des
axes, et en changeant certaines options :
> x<-pi*c(0:200)/50
Graphe de cos(X) en fonction de X
> y<-cos(x)
1.5
> plot(x,y,
1.0
xlab="Variable X",ylab="Cos(X)",
main="Graphe de cos(X) en fonction de X",
0.5
0.0
xlim=c(0,max(x)),ylim=c(-1.5,1.5),
−0.5
type="b",lty=2,pch=3,font.axis=3,
col="DarkRed")
−1.0
−1.5
0 2 4 6 8 10 12
Variable X
intervalle 0−4 pi
Note : Sous Splus les couleurs ne sont pas prédéfinies de la même manière aussi l’option col="DarkRed" n’est pas
valide. On peut utiliser des numéros de couleurs (1 pour noir, etc...).
Comme c’est une des options les plus utiles, le graphe ci-dessous montre les différents types de graphes
que l’on peut obtenir avec l’option type.
>x1<-pi*c(0:20)/5
type="p" type="l"
>y1<-cos(x1)
1.0
1.0
0.5
0.5
>par(mfrow=c(3,2))
0.0
0.0
y1
y1
−1.0 −0.5
−1.0 −0.5
0 2 4 6 8 10 12 0 2 4 6 8 10 12 >plot(x1,y1,type="p",main="type=\"p\"")
x1 x1
1.0
>plot(x1,y1,type="o",main="type=\"o\"")
0.5
0.5
0.0
0.0
y1
y1
>plot(x1,y1,type="h",main="type=\"h\"")
−1.0 −0.5
−1.0 −0.5
0 2 4 6 8 10 12 0 2 4 6 8 10 12
x1 x1 >plot(x1,y1,type="s",main="type=\"s\"")
type="s" type="n"
>plot(x1,y1,type="n",main="type=\"n\"")
1.0
1.0
0.5
0.5
0.0
0.0
y1
y1
−1.0 −0.5
−1.0 −0.5
0 2 4 6 8 10 12 0 2 4 6 8 10 12
x1 x1
On peut aussi vouloir rajouter des éléments après avoir avoir tracé un premier graphe. Pour cela il
existe un certain nombre de fonctions graphiques spécifiques, résumées dans la table 3.2.
46 Chapitre 3. Graphes
TAB . 3.2 : Fonctions graphiques permettant d’ajouter des éléments à un graphe existant.
Note : La fonction rect() n’existe pas sous Splus (mais on peut s’en sortir en utilisant la fonction lines plusieurs fois).
Les fonctions points() et lines() sont très utiles pour ajouter une deuxième courbe sur un graphe, ou
pour superposer des courbes à des données. Elles peuvent être utilisées avec des vecteurs. Par exemple,
pour superposer la courbe de y=sin(x) sur le nuage de points correspondant à y=cos(x), on peut écrire :
1.0
0.5
> x<-pi*c(0:20)/5
> y<-cos(x)
0.0
y
> plot(x,y)
> lines(x,sin(x))
−0.5
−1.0
0 2 4 6 8 10 12
Remarquez qu’on a utilisé directement lines(x,sin(x)) au lieu de définir une variable sin(x). On aurait
bien sûr pu écrire aussi plot(x,cos(x)) sans définir y.
La fonction legend(), qui permet de rajouter une légende à un graphe, est particulièrement utile. On
peut ainsi superposer plusieurs courbes sur le même graphe, ou différencier des sous-groupes avec des
symboles et des couleurs différentes. Le texte de la légende est obligatoire (un vecteur de chaînes de ca-
ractères de taille correspondant au nombre d’éléments de la légende), ainsi que le positionnement de la
3.1 Fonctions graphiques 47
Ajoutons une légende au graphe précédent, en changeant la ligne utilisée pour tracer y=sin(x) en une
ligne pointillée :
1.5
Sin(X)
Cos(X)
1.0
> plot(x,y,
0.5
xlab="Variable X",ylab="",
0.0
xlim=c(0,max(x)),ylim=c(-1.5,1.5),
type="o",lty=2,col=2)
−0.5
> lines(x,sin(x),col=1)
−1.0
> legend(3,1.5,c("Sin(X)","Cos(X)"),
−1.5
lty=1:2,col=1:2,pch=c(-1,1))
0 2 4 6 8 10 12
Variable X
On utilise la fonction abline() pour des lignes droites. On verra son usage pour tracer la droite de
régression dans la section 4.2, pour l’heure servons-nous en pour rajouter la ligne des abscisses. Pour cela
on utilise l’option h=0 (bien évidemment, v=0 trace une ligne verticale pour l’axe des ordonnées) :
1.0
0.5
> plot(x,y,
+ xlab="Variable X",ylab="Cos(X)")
Cos(X)
0.0
> lines(x,sin(x))
> abline(h=0)
−0.5
−1.0
0 2 4 6 8 10 12
Variable X
La fonction plot() est la fonction graphique dite "générique" de R, c’est-à-dire que c’est une fonction
qui essaie de tracer le graphe le plus adapté avec le type de données qu’on lui donne. Il existe aussi des
48 Chapitre 3. Graphes
fonctions graphiques permettant de faire des graphes particuliers. La liste de ces fonctions est donnée en
table 3.3.
hist() histogramme
barplot() graphe en barre
boxplot() boîte à moustache
qqplot(), qqnorm() graphe quantile-quantile
pie() camembert
tsplot() graphe de séries temporelles
pairs() corrélations entre les colonnes d’une matrice
matplot() corrélations entre les colonnes de deux matrices
persp() graphe en 3D
contour() surface 3D
Les fonctions pairs() et matplot() sont très similaires, elles peuvent être utilisées pour déterminer sur un
jeu de données présenté sous forme de matrice les corrélations entre les différentes variables.
Voici un exemple d’utilisation de la fonction pairs() pour tracer les corrélations entre des paramètres
estimés par régression non linéaire individuelle chez 53 sujets :
2 4 6 8
35
30
25
kel0
20
15
10
5
8
>param<-matrix(scan("plots/parfitte.dat"),
6
kinh ncol=7,byrow=T)
4
> nampar<-c("kmet","kaft","vdft",
2
"kel0","kinh","vdfu")
300
250
> pairs(param[,c(5:7)],
200
vdfu
150
labels=nampar[c(4:6)])
100
50
On a défini un vecteur nampar contenant les noms des paramètres, et on a utilisé ce vecteur pour
définir les noms apparaissant dans les cases de la diagonale, grâce à l’option labels. Par défaut, on obtient
une disposition en matrice rappelant la matrice des paramètres donnés à la fonction. Mais on peut aussi
mettre des graphes différents dans la matrice triangulaire du haut et dans celle du bas, ou bien mettre du
texte à la place de certains graphes, ou bien rajouter des lignes de régression. Tout ceci est paramétrable
grâce aux options upper.panel et lower.panel.
3.1 Fonctions graphiques 49
Voici un exemple d’utilisation de la fonction hist(). L’option breaks permet de contrôler le nombre de
classes utilisées pour tracer l’histogramme :
Histogram of xgaus
10
8
6
Frequency
> xgaus<-rnorm(100)
> hist(xgaus,breaks=20)
2
0
−2 −1 0 1 2
xgaus
Le titre du graphe ainsi que les axes sont affichés automatiquement par hist(), mais comme avec plot(),
il est possible de choisir ses propres noms.
Note : nous verrons la fonction rnorm() au début du chapitre suivant, c’est une fonction permettant de tirer un
échantillon aléatoire dans une loi normale. Ici nous l’avons utilisée pour tirer un échantillon de taille 100 pour
les besoins du graphe.
Voici un exemple d’utilisation de la fonction boxplot(). On a utilisé l’option varwidth=T pour que la taille
des boîtes soit fonction du nombre d’observations dans chaque vecteur.
3
2
1
0
> xgaus<-rnorm(500)
−1
> ygaus<-runif(60)
> boxplot(xgaus,ygaus,varwidth=T)
−2
1 2
L’option at de boxplot() permet de spécifier l’endroit sur l’axe des x où chaque boîte va être placée.
En combinant cette option, l’option add=T qui superpose le graphe à un graphe déjà existant, et l’option
boxwex pour contrôler l’épaisseur des boîtes, on peut obtenir une série de boîtes à moustaches représentant
l’évolution d’un phénomène au cours du temps. Par exemple, ici on simule un vecteur de temps et à chaque
√
temps x, 30 observations tirées de la courbe y= x. Ensuite on fait un graphe de y en fonction de x sans
50 Chapitre 3. Graphes
tracer les points (option type="n") et on ajoute la boîte à moustache en séparant les groupes formule y∼x
(on reviendra aux formules en abordant l’exemple de la régression non linéaire en section 4.2).
Un exemple d’une telle utilisation est donné par :
6
> xtim<-rep(seq(0,24,by=4),each=30)
> ypl<-xtim
4
ypl[i]<-rnorm(1,mean=sqrt(xtim[i]))}
2
> plot(xtim,ypl,type="n",
xlab="Time",ylab="Data")
0
> boxplot(ypl~xtim,boxwex=1.5,
0 5 10 15 20
at=sort(unique(xtim)),add=T,axes=F)
Time
Les plots quantile-quantile sont utilisées pour comparer graphiquement la distribution d’un échan-
tillon aléatoire avec une distribution théorique attendue (fonction qqnorm() pour la loi normale), ou avec
celle d’un autre échantillon aléatoire (fonction qqplot()). On peut par exemple faire le QQ-plot contre la
distribution normale de notre variable xgaus :
> xgaus<-rnorm(500)
Sample Quantiles
> qqnorm(xgaus)
0
> qqline(xgaus)
−1
−2
−3 −2 −1 0 1 2 3
Theoretical Quantiles
La fonction qqline() permet de rajouter la ligne unité au graphe. Les graphes quantile-quantile sont
généralement utilisés pour évaluer la distribution de résidus d’une analyse statistique, afin de vérifier s’ils
se conforment aux hypothèses du modèle.
3.1 Fonctions graphiques 51
4 3
5 2
> pie(rep(1,12),
6 1
col=rainbow(12),radius = 0.9)
7 12
8 11
9 10
Enfin, utilisons la fonction persp() pour faire un graphe 3D d’une fonction trigonométrique.
> x<-pi*c(0:20)/5
> y<-x
> f <- function(x,y) {
+ r <- sqrt(x^2+y^2)
z
+ 10 * sin(r)/r}
> z <- outer(x, y, f)
y
> persp(x,y,z)
x
Dans cet exemple, on a d’abord créé deux vecteurs x et y qui sont les axes des abscisses et des ordonnées.
sin(x2 + y 2 )
Puis on a défini une fonction f qui calcule la valeur de 10 pour x et y donné (voir chapitre 5.3).
x2 + y 2
On a utilisé la fonction outer() qui calcule la valeur d’une fonction pour chaque point d’une grille délimitée
par un vecteur des x et un vecteur des y (donc une matrice de taille length(x)×length(y)) . Puis on a tracé la
surface résultante.
La fonction lowess() est utilisée pour obtenir une interpolation à travers un nuage de points (x,y). On
trace le nuage de points par plot() puis on superpose le résultat du lissage en utilisant la fonction lines().
52 Chapitre 3. Graphes
Dans le graphe qui suit, on a utilisé un jeu de données de R appelé cars et qui contient les distances de
freinage en fonction de la vitesse pour une série de voitures.
120
100
> data(cars)
80
Distance de freinage
> plot(cars[,1],cars[,2],
60
xlab="Vitesse",
40
ylab="Distance de freinage")
> lines(lowess(cars[,1],cars[,2]))
20
0
5 10 15 20 25
Vitesse
Splines
Les splines sont un ensemble de fonctions particulières, possédant un certain nombre de propriétés
mathématiques intéressantes. Elles sont définies par un ensemble de points appelés noeuds et par le degré
d, qui est le degré des fonctions polynômiales utilisées pour les construire. Une fonction spline coïncide
avec un polynôme de degré d sur un intervalle entre deux noeuds. La fonction et ses (d-1)ièmes dérivées
sont continues. Pour les splines d’interpolation, la valeur de la spline est égale à la valeur de la fonction
interpolée en chaque noeud.
La fonction spline(), disponible dans les fonctions de base de R, permet d’obtenir l’interpolation par
splines d’une courbe.
0.5
0.0
−0.5
> x<-pi*c(0:10)/5
y
> y<-cos(x)*rnorm(length(x))
−1.0
> plot(x,y)
−1.5
> lines(spline(x,y))
−2.0
0 1 2 3 4 5 6
Contrairement à lowess(), cette fonction ne marche pas à travers un nuage de points, puisqu’elle passe
par tous les points.
La fonction smooth.spline() est utilisée pour obtenir la décomposition en splines.
3.1 Fonctions graphiques 53
Il existe également une librairie spécialisée dans les splines, et qui est très logiquement appelée splines.
On y trouve la décomposition sur la base des splines cubiques naturels (fonction ns()). Les splines cu-
biques sont des splines de degré d=3. Les splines dit naturels satisfont des conditions de continuité aux
bornes (noeuds extrêmes) qui les rendent particulièrement adaptés pour l’interpolation de fonction. On
dispose aussi de la fonction bs() pour décomposer la fonction sur la base des B-splines, qui sont une base
de splines de lissage, ayant des propriétés de continuité voisines des splines d’interpolation . Contraire-
ment aux splines d’interpolation, les B-splines ne passent pas par les noeuds de la fonction à interpoler,
mais s’en approchent, et on peut spécifier plusieurs fois le même noeud pour forcer la fonction à passer
par un noeud donné.
La librairie modreg est une librairie spécialisée qui contient de nombreuses fonctions pour effectuer de
la régression non paramétrique. Le résultat de cette régression peut être utilisé pour obtenir le lissage d’un
graphe.
Dans cette librairie, la fonction loess() est utilisée pour obtenir une interpolation à travers un nuage de
points (x,y). L’interpolation est locale (dans un voisinage de x) par défaut mais on peut aussi spécifier une
interpolation globale. On peut contrôler l’étendue du lissage ainsi que le degré des polynômes utilisés.
120
100
> plot(cars[,1],cars[,2],
80
Distance de freinage
xlab="Vitesse",
60
ylab="Distance de freinage")
40
> lines(loess(cars[,2]~cars[,1]))
20
0
5 10 15 20 25
Vitesse
La fonction scatter.smooth() est utilisée pour tracer un nuage de points (x,y) et y superposer le résultat
d’un lissage par splines.
120
100
80
> scatter.smooth(cars[,2]~cars[,1])
cars[, 2]
60
40
20
0
5 10 15 20 25
cars[, 1]
La fonction par() contrôle la plupart des options graphiques de R. Lorsqu’on appelle la fonction plot(),
les options comme pch ou lty sont en réalité inutilisées par cette fonction, et elles sont en fait récupérées
par la fonction par() qui les utilise pour modifier l’environnement graphique pour le graphe demandé. On
peut modifier directement l’environnement graphique global, et les modifications porteront alors sur tous
les graphes demandés. Par exemple, on peut vouloir changer le symbole par défaut utilisé pour tracer des
nuages de points en un triangle, en tapant :
>par(pch=2)
Les options de par() sont extrêmement nombreuses. Nous en avons vu certaines dans notre survol de
plot(), les autres sont dans la documentation. Citons simplement la possibilité de rendre l’affichage des
graphes interactifs, en tapant :
>par(ask=T)
Ainsi, R s’arrête avant d’effacer une page graphique et attend l’autorisation de continuer (pratique quand
on veut faire une série de graphiques à passer en revue, sans tous les mettre sur la même page).
3.2 Environnement graphique 55
Une autre option très utile est la possibilité de superposer deux graphes. On a vu qu’on pouvait rajouter
des courbes ou des points à un graphe déjà existant. Supposons maintenant qu’on ait envie de superposer
deux types de données sur le même graphique. Par exemple, superposons les courbes y=cos(x) et y=2 sin(x)
sur le même graphe :
2
1
> x<-pi*c(0:200)/50
> y<-cos(x)
0
zy
> z<-2*sin(x)
> plot(x,y,ylim=c(-2,2),type="l")
−1
> par(new=T)
> plot(x,z,ylim=c(-2,2),type="l")
−2
0 2 4 6 8 10 12
Comme les échelles des axes des ordonnées sont différentes pour les deux courbes, on a utilisé l’option
ylim pour imposer la même limite aux deux graphes. En revanche comme les deux graphes utilisent le
même vecteur pour l’axe des abscisses, on n’a pas besoin de préciser des limites pour cet axe.
On utilise l’option par(mfrow=c(m,n)) pour créer une page de m×n figures où m donne le nombre de
rangées et n le nombre de colonnes. On peut également contrôler l’apparence des graphes en demandant
par exemple une zone de tracé carrée, en utilisant l’option pty="s" de la fonction par(). Par exemple pour
créer une page de 2 fois 3 graphes carrés :
>par(mfrow=c(2,3),pty="s")
Si on veut complètement ajuster l’apparence d’une page, il existe la fonction layout() qui permet de faire
à peu près ce qu’on veut avec l’apparence, comme par exemple mettre une grande figure sur la moitié de
la page puis diviser le bas de la page en 3 figures dont celle du milieu sera tournée de 90 degrés... Reportez
vous à la documentation pour la syntaxe précise.
Note : la fonction layout() ne semble pas exister sous Splus.
première figure de ce chapitre (toutes mes figures sont rassemblées dans un sous-répertoire plots de mon
répertoire de travail), j’ai utilisé les commandes :
>x<-pi*c(0:200)/50
>y<-cos(x)
>postscript("plots/fig3_1.ps")
>plot(x,y)
>dev.off()
Tous les graphes de ce manuel ont été exportés sous format postscript et intégrés dans le fichier LATEX en
utilisant le module epsfig.
Pour ceux qui travaillent sous Windows ou qui ont besoin d’échanger des fichiers graphiques, le format
d’échange standard est plutôt JPEG (Joint Photographic Experts Group), le format le plus utilisé pour la
compression de photographies. La fonction s’appelle jpeg() et elle s’utilise avec comme argument le nom
du fichier graphique.
> jpeg("plots/fig3_1.jpeg")
> plot(x,y)
> dev.off()
On peut aussi définir la taille des images avec les options width et height, ou la qualité avec l’option quality,
ainsi que la couleur du fond.
Enfin, un autre format utile est le format PNG (Portable Network Graphic), une amélioration du format
GIF supportant entre autres la transparence par l’intermédiaire du canal α. De plus PNG est un format libre
contrairement à GIF qui nécessite une license d’utilisation (et vive le logiciel libre !). La fonction png() est
utilisée pour créer des graphiques dans ce langage, et elle utilise les mêmes options que jpeg().
Note 1 : Sous Windows, png() et jpeg() n’existent pas mais on peut sauver les graphes dans le format désiré en
passant par les menus. Une autre option est d’utiliser la fonction export.graph() qui permet d’exporter un
graphique fait par l’interface graphique en spécifiant son type.
Note 2 : Evidemment, Windows ne connaît pas postscript et il faut utiliser le programme Ghostscript pour lire des
fichiers postscript, mais il est vivement conseillé d’installer Ghostscript de toute façon car il permet notamment
de convertir en format PDF...
Chapitre 4
Analyses statistiques
Nous allons commencer ce chapitre par les statistiques descriptives et les distributions statistiques les
plus courantes. Nous détaillerons ensuite la régression non linéaire, en montrant comment spécifier un
modèle de régression, et comment lire les résultats obtenus. Nous utiliserons les graphes du chapitre 3
pour visualiser l’ajustement et tracer des graphiques de diagnostic. Dans la dernière partie, nous verrons
d’autres modèles d’analyse utiles.
> vec<-1:20
> summary(vec)
Min. 1st Qu. Median Mean 3rd Qu. Max.
1.00 5.75 10.50 10.50 15.25 20.00
Si les données comprennent des valeurs manquantes (NA), le nombre de valeurs manquantes est donné et
les statistiques de summary données sur les valeurs non manquantes.
> vec<-c(vec,NA)
> summary(vec)
Min. 1st Qu. Median Mean 3rd Qu. Max. NA’s
1.00 5.75 10.50 10.50 15.25 20.00 1.00
Note : si summary() est appliquée à un objet provenant d’une analyse statistique, ou de types définis par certaines
librairies, on peut avoir soit un résumé de l’analyse, soit un résumé des caractéristiques de l’objet.
Les valeurs données peuvent aussi être estimées indépendamment. Les principales fonctions sont don-
nées dans la table 4.1 ci-dessous.
57
58 Chapitre 4. Analyses statistiques
Note : Il n’y pas de fonction donnant directement l’écart-type donc on utilise sqrt(var(x)).
Par défaut on obtient comme résultat NA si les données contiennent des valeurs manquantes. Sous R,
pour toutes ces fonctions l’option permettant d’enlever les valeurs manquantes est identique : na.rm=T.
> median(vec,na.rm=T)
[1] 10.5
> quantile(vec,c(0.05,0.95),na.rm=T)
5% 95%
1.95 19.05
Note : Sous Splus, les options sont différentes selon les fonctions. Par exemple pour mean() c’est na.rm=T alors que
pour var() c’est na.method="fail" .
R dispose des fonctions statistiques les plus courantes plus d’autres qu’on utilise beaucoup moins. Pour
chaque distribution connue, quatre fonctions sont prédéfinies. Par exemple, pour la loi normale, le suffixe
est "norm" et les 4 fonctions sont donc :
• dnorm() : densité
(x − µ)2
1 −
f (x) = √ e 2σ 2
2πσ
• pnorm() : probabilité Z x
F (x) = P(X ≤ x) = f (x) dx
−∞
• qnorm() : quantile correspondant de la distribution, c’est-à-dire pour αq donné la valeur de x pour
laquelle
F (x) = P(X ≤ x) = αq
> pnorm(0)
[1] 0.5
4.1 Statistiques descriptives 59
> qnorm(c(0.025))
[1] -1.959964
> 1-pnorm(1.96)
[1] 0.02499790
On peut également spécifier la moyenne µ et l’écart-type σ, par exemple pour tirer un échantillon aléatoire
de taille 4 dans N (2, 0.5) :
> rnorm(4,2,0.5)
[1] 0.9670748 1.0382319 2.1925202 2.0653701
> x1<-rnorm(20,2)
> x2<-rnorm(20)
> t.test(x1,x2)
data: x1 and x2
t = 4.8168, df = 33.802, p-value = 3.002e-05
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
0.8510836 2.0938348
sample estimates:
mean of x mean of y
1.56489554 0.09243633
60 Chapitre 4. Analyses statistiques
Γ(n+x)
dnbinom() binômiale négative BN (n, p) Γ(n) x! pn (1 − p)x (†)
(k−x)
x Cn
dhyper() Hypergéométrique H(m, n, k) Cm C( m+n)k
Γ(α+β)
dbeta() Beta β(α, β) Γ(α) Γ(β) x(α−1) (1 − x)(β−1) (†)
x
dgamma() Gamma Γ(γ, β = 1) γ
1
xγ−1 e− β (†)
β Γ(γ)
1
dcauchy() Cauchy C(α, β) x−α 2
πβ (1 + ( )
β
1 n −x
dchisq() chi-deux χ2 (n) (†) n x 2 −1 e 2
2 Γ(n/2)
2
n +n
Γ( 1 2 2 ) n1 n1 n1 +n2
df() F F(n1 , n2 ) Γ(n1 /2) Γ(n2 /2) ( nn12 ) 2 x 2
−1
(1 + n1
n2 x)− 2
TAB . 4.2 : Principales distributions disponibles dans R. Le nom de la fonction calculant la densité est donné dans le
tableau, les autres s’en déduisent en changeant le "d" initial par "p" (probabilité), "q" (quantiles) ou "r" (échantillon
aléatoire).
4.1 Statistiques descriptives 61
Comme d’habitude, le résultat de cette fonction est une liste, donc si on l’affecte à une variable y, on
peut accéder à différents éléments de la liste. Par exemple, on peut extraire seulement la valeur p du test,
en faisant référence à l’élément p$value de la liste :
> y<-t.test(x1,x2)
> y$p.val
[1] 3.001682e-05
> y$statistic
t
4.8168
> y$param
df
33.80233
> y$est
mean of x mean of y
1.56489554 0.09243633
Note : on peut abréger les noms quand il n’y a pas d’ambiguïté avec un autre nom de la liste. Ici on appelle y$est au
lieu de y$estimate, ou y$p.val au lieu de y$p.value.
Le résultat de tous les tests donnés dans le tableau 4.3 est un objet de type htest. Cette liste contient
notamment un élément p.value donnant la valeur p du test, et un élément statistic donnant la valeur de la
statistique de test, comme on l’a vu plus haut pour le test t.
Remarque : Par défaut une seule méthode est définie pour un objet de type htest, la méthode print.htest qui affiche
le résultat du test après mise en forme standardisée.
62 Chapitre 4. Analyses statistiques
Il existe aussi des librairies spécialisées où un grand nombre de tests statistiques ont été programmés.
La librairie ctest qui est chargée par défaut à l’ouverture du programme est celle où la plupart des tests
du tableau 4.3 sont définies. Elle comprend aussi des fonctions de calcul de la puissance pour des tests t
(fonction power.t.test()), ou pour des tests de proportions (fonction power.prop.test()). Des tests spécialisés
sont disponibles dans des librairies comme survival pour tester des modèles de survie, ou ts pour les tests
portant sur les séries temporelles.
4.2.1 Exemple
Nous allons utiliser comme exemple un jeu de données interne de R, baptisé cars et qui contient la
distance d’arrêt cars$dist mesurée en fonction de la vitesse cars$speed pour un certain nombre de voitures
(en 1920). Nous avons déjà utilisé ce jeu de données en section 3.1.3. Les vitesses sont en miles par heure et
les distances de freinage en pieds. On appelle le jeu de données en utilisant la fonction data() :
120
100
> data(cars)
80
> cars
dist
speed dist
60
1 4 2
40
2 4 10
20
3 7 4
....
0
5 10 15 20 25
Ce jeu de données semble être un assez bon candidat à une régression linéaire.
Nous allons donc faire la régression linéaire de la distance de freinage en fonction de la vitesse. La
régression d’une variable y sur un prédicteur x s’écrit en langage R y∼x et cette syntaxe s’appelle une
formule. Pour l’instant nous n’avons pas encore effectué la régression, nous avons juste par cette formule
spécifié notre modèle, qui en termes statistiques s’écrirait :
y =x+ǫ (4.1)
La fonction permettant de faire une régression est la fonction lm() et, selon un principe que vous com-
mencez maintenant à bien comprendre, nous mettons la formule (qui est un genre de fonction) dans la fonc-
tion lm() pour effectuer la régression par lm() sur notre modèle y∼x, où ici y=cars$dist et x=cars$speed :
> lm(dist~speed,data=cars)
Call:
4.2 La régression linéaire 63
On aurait également pu appeler lm() en spécifiant le jeu de données et en ne donnant que les noms des
variables.
> y<-lm(dist~speed,data=cars)
Il est recommandé d’utiliser cette syntaxe, si on veut utiliser y par la suite pour prédire la valeur du modèle
sur de nouvelles données.
4.2.3 Résultats
Comme d’habitude, on peut affecter le résultat de ce calcul à un objet, afin d’en garder une trace et de
pouvoir le manipuler.
> y<-lm(dist~speed,data=cars)
> y
Call:
lm(formula = dist ~ speed, data = cars)
Coefficients:
(Intercept) speed
-17.579 3.932
y étant un objet de type lm, il contient un certain nombre de données intéressantes, créés par la fonction
lm() et rassemblés en une liste. Voyons quels éléments contient cette liste, avec la fonction attributes() :
> attributes(y)
$names
[1] "coefficients" "residuals" "effects" "rank"
[5] "fitted.values" "assign" "qr" "df.residual"
[9] "xlevels" "call" "terms" "model"
$class
[1] "lm"
Si on veut par exemple visualiser les estimations des paramètres réalisées par le modèle, c’est l’élément
coefficients de la liste :
> y$coefficients
(Intercept) speed
-17.579095 3.932409
Il est également possible d’utiliser la fonction coefficients() ou son alias coeff() qui donnent le même résul-
tat :
> coef(y)
(Intercept) speed
-17.579095 3.932409
64 Chapitre 4. Analyses statistiques
Imaginons qu’on veuille tracer la droite de régression à la main (on verra qu’on peut utiliser d’autres
techniques automatiques pour faire ça, ainsi que des fonctions spécialisées, mais cet exemple a pour but de
montrer la manipulation des éléments de la liste). On va mettre les coefficients dans un vecteur intermé-
diaire, tracer les observations, puis superposer une droite correspondant à la régression :
> param<-y$coefficients
> ymx<-max(cars$dist)
120
> xplot<-c(min(cars$speed),
100
max(cars$speed))
> yplot<-xplot*param[2]+param[1]
80
Distance de freinage
> plot(cars$speed,cars$dist,
60
ylab="Distance de freinage",
40
xlab="Vitesse",ylim=c(0,ymx),xlim=xplot)
> par(new=T)
20
> plot(xplot,yplot,xlab="",ylab="",
0
5 10 15 20 25 type="l",ylim=c(0,ymx),xlim=xplot)
Vitesse
La méthode summary() est l’une des premières fonctions que l’on va appliquer au résultat de la régres-
sion, car elle produit un résumé des caractéristiques du modèle et de la qualité de l’ajustement :
> summary(y)
Call:
lm(formula = dist ~ speed, data = cars)
Residuals:
Min 1Q Median 3Q Max
-29.069 -9.525 -2.272 9.215 43.201
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -17.5791 6.7584 -2.601 0.0123 *
speed 3.9324 0.4155 9.464 1.49e-12 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Cette fonction donne la formule (le modèle) utilisée, l’estimation des paramètres ainsi que leurs erreurs
standards associées, et la valeur de la statistique de test indiquant s’il faut les conserver dans le modèle,
et des statistiques concernant la qualité de l’ajustement (R2 , R2 ajusté, erreur résiduelle, nombre de degrés
de liberté). En réalité, lorsque on applique summary() à un objet de type lm, R reconnaît qu’il s’agit là d’un
objet particulier et il applique la fonction summary.lm() qui est spécifique des objets de type lm.
Note : on retrouvera ce format pour les autres analyses statistiques, et une méthode similaire peut être développée
pour ses propres analyses. On peut s’inspirer pour cela de la méthode elle-même. On peut visualiser cette
fonction comme tous les objets en tapant son nom (sans les parenthèses donc) sur la ligne de commande.
L’objet y contient bien les coefficients de la régression mais pas l’erreur d’estimation. En revanche on
peut utiliser summary() qui en tant que fonction renvoit également comme objet une liste dont on peut voir
en utilisant attributes() qu’elle contient les coefficients, mais sous format d’un tableau incluant les erreurs
d’estimation. On peut donc utiliser ce tableau plus complet en utilisant summary(y)$coefficients :
> summary(y)$coefficients
Estimate Std. Error t value Pr(>|t|)
(Intercept) -17.579095 6.7584402 -2.601058 1.231882e-02
speed 3.932409 0.4155128 9.463990 1.489836e-12
> summary(y)$coefficients[1,2]
[1] 6.75844
Ainsi, on peut utiliser ces données pour les stocker dans un autre vecteur, les manipuler pour calculer
le coefficient de variation ou l’intervalle de confiance, etc... Vous commencez à comprendre comment ça
marche maintenant !
Appliquée à un objet de type lm, la méthode plot appelle comme pour summary la fonction spécifique
plot.lm(), et trace quatre graphiques permettant d’avoir des informations sur la qualité de la régression. Le
premier est un graphe des résidus en fonction des prédictions, le deuxième un graphe quantile-quantile
des résidus, et les deux derniers sont des graphes visant à détecter des individus aberrants (scale-location
plot et distance de Cook).
Note : Splus ne donne pas les mêmes graphes par défaut que R.
66 Chapitre 4. Analyses statistiques
3
23 49 49
40
23
Standardized residuals
35
35
2
20
Residuals
1
0
0
−20
−1
−2
0 20 40 60 80 −2 −1 0 1 2 > par(mfrow=c(2,2))
Fitted values Theoretical Quantiles
> plot(y)
Scale−Location plot Cook’s distance plot
23 49
49
1.5
0.3
35
Standardized residuals
Cook’s distance
1.0
0.2
0.5
0.1
23
39
0.0
0.0
0 20 40 60 80 0 10 20 30 40 50
Personnalisation
On peut bien sûr faire ses propres graphiques en utilisant l’objet issu de la régression. On a vu plus
haut qu’on pouvait utiliser les paramètres estimés pour calculer la valeur du modèle pour d’autres points.
On aurait pu utiliser également la méthode predict, qui appelle la fonction predict.lm() pour l’objet de notre
régression.
> predict(y,data.frame(speed=xplot))
1 2
-1.84946 80.73112
Note : c’est ici qu’il faut avoir appelé lm() avec l’option data=cars pour disposer explicitement du nom "speed", sinon
il est impossible de définir un nouveau jeu de données pour la prédiction.
La méthode residuals() aussi abrégée en resid() permet d’extraire les résidus : pour un objet de type lm,
selon les options on peut obtenir les résidus pondérés ou non. De même la méthode fitted.values fournit les
valeurs prédites. Pour refaire le premier des 4 graphes par défaut en échelle logarithmique, on peut écrire :
40
> plot(fitted.values(y),resid(y,
"pearson"),log="x",
20
Résidus pondérés
Warning message:
2 x values <= 0 omitted from
−20
R nous avertit que certaines valeurs étaient négatives et ne peuvent donc pas être tracées sur un graphe
en échelle logarithmique...
Une façon très pratique de tracer la droite de régression est d’utiliser la fonction abline() que nous
avions déjà utilisé pour tracer une ligne horizontale ou verticale sur un graphique. Si on donne à abline()
l’objet y, elle en extrait l’intercept et la pente pour tracer la droite de régression par dessus un autre graphe :
120
100
80
> plot(cars)
dist
60
> abline(y)
40
20
0
5 10 15 20 25
speed
On peut spécifier un modèle sans intercept en incluant le terme -1 dans la formule statistique utilisée
pour la régression :
> y1<-lm(dist~speed-1,data=cars)
Une fonction utilisée pour visualiser l’apport d’un terme à une régression linéaire est la fonction anova().
Appliquée à l’objet y de la régression originelle, cette fonction donne la probabilité pour chacun des termes
que le paramètre estimé soit significativement différent de zéro :
> anova(y)
Analysis of Variance Table
Response: dist
Df Sum Sq Mean Sq F value Pr(>F)
speed 1 111949 111949 423.47 < 2.2e-16 ***
Residuals 49 12954 264
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Appliqué à une série de régressions linéaires sur un même jeu de données, anova() donne une table avec
la somme des carrés pour chacun des modèles, et la valeur du test F indiquant si le modèle est significati-
vement meilleur que le précédent. Ceci n’a de sens que pour des modèles emboîtés :
68 Chapitre 4. Analyses statistiques
> anova(y1,y)
Analysis of Variance Table
Note : anova() est une méthode. Lorsqu’elle est utilisée pour des objets de type lm, elle appelle en réalité anova.lm().
On peut notamment changer le test (par défaut, un test F) utilisé pour tester la significativité.
Il existe aussi la fonction aov() qui ajuste une régression linéaire sur chaque terme du modèle et res-
semble un peu dans ses sorties à anova().
Si on veut refaire une analyse en changeant seulement le modèle, sans spécifier à nouveau tout le cadre
de la régression, on peut utiliser la fonction update() en utilisant un objet issu d’une précédente régression.
Par exemple, on aurait pu utiliser cette fonction pour comparer le résultat y de notre régression complète
avec celui d’une régression sans intercept, en écrivant :
> update(y,.~.-1)
Call:
lm(formula = dist ~ speed - 1, data = cars)
Coefficients:
speed
2.909
Les points dans la formule signalent qu’on utilise les mêmes éléments que précédemment. On aurait pu
également répéter la formule en entier :
> update(y,dist~speed-1)
La régression peut comprendre plusieurs termes. Si le jeu de données comprenait également une co-
lonne donnant l’âge du conducteur, on aurait pu faire une régression multivariée en tapant une commande
du style :
> lm(dist~speed+age)
Lorsqu’il y a plusieurs prédicteurs, on peut prendre en compte l’interaction entre les deux en utilisant un
signe * à la place du signe + :
> lm(dist~speed*age)
> lm(dist~speed:age)
4.2 La régression linéaire 69
Ici on aurait une régression seulement sur l’interaction entre speed et age.
D’autres fonctions peuvent être utilisées à l’intérieur de la formule statistique, notamment poly() qui
permet de spécifier un polynôme de degré souhaité de la variable, ou les fonctions de splines de la librairie
splines qui permettent d’inclure un lissage non paramétrique. Par exemple, si on veut voir quel effet a
l’addition d’un terme quadratique en speed à notre régression précédente :
> summary(update(y,dist~poly(speed,2)))
Call:
lm(formula = dist ~ poly(speed, 2), data = cars)
Residuals:
Min 1Q Median 3Q Max
-28.720 -9.184 -3.188 4.628 45.152
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 42.980 2.146 20.026 < 2e-16 ***
poly(speed, 2)1 145.552 15.176 9.591 1.21e-12 ***
poly(speed, 2)2 22.996 15.176 1.515 0.136
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Le résultat nous dit qu’ici, il n’est pas nécessaire de supposer une dépendance quadratique en plus de la
dépendance linéaire.
Note : les prédicteurs peuvent également être des catégories (variables discrètes, exemple : le sexe) lorsque l’on
utilise la fonction lm.
> y1<-lsfit(cars$speed,cars$dist)
> ls.print(y1)
Residual Standard Error=15.3796
R-Square=0.6511
F-statistic (df=1, 48)=89.5671
p-value=0
70 Chapitre 4. Analyses statistiques
Nous avons vu que lm() permettait de faire une régression linéaire multivariée. Toutefois, cette fonc-
tion ne permet pas de spécifier une forme différente pour la distribution des erreurs, ni d’effectuer une
transformation de la réponse. La fonction glm() est utilisée pour ajuster des modèles de régression linéaire
généralisée. Elle permet d’étendre les modèles ajustés notamment au cas de la régression logistique.
En plus de la formule statistique déjà vue pour lm(), il faut spécifier la distribution de l’erreur. Pour
un modèle de régression logistique (logit), l’option à utiliser est family=binomial, qui spécifie par défaut
l’utilisation d’un logit pour la transformation de la réponse (on peut aussi utiliser une fonction probit).
La modélisation de données de comptage par une loi de Poisson peut également être effectuée en
utilisant glm(), avec l’option family=poisson.
Le jeu de données icu trouvé sur le site du DASL http ://lib.stat.cmu.edu/DASL/ contient
les données de survie de 200 patients admis dans une unité de soins intensifs (partie d’une étude plus
large). La variable STA contient l’état dans lequel le patient est sorti du service (0=vivant, 1=mort), et le
jeu de données contient un ensemble de variables discrètes ou continues, comme l’âge (AGE), la présence
d’une infection à l’entrée (INF), si le patient est entré en urgence ou sur rendez-vous (TYP), des variables
biologiques, et l’état de conscience (LOC). Imaginons qu’on veuille faire une régression logistique de la
survie en fonction de l’âge, l’infection, le type d’entrée et l’état de conscience :
>icu<-read.table("../data/icusurv.dat",header=T)
>icu<-as.data.frame(icu)
> model1<-glm(STA~AGE+TYP+LOC+INF,family=binomial,data=icu)
> summary(model1)
Call:
glm(formula = STA ~ AGE + TYP + LOC + INF, family = binomial,
data = icu)
Deviance Residuals:
Min 1Q Median 3Q Max
-2.4327 -0.6461 -0.3506 -0.2349 2.5356
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) -9.71662 1.78324 -5.449 5.07e-08 ***
AGE 0.03029 0.01208 2.508 0.012147 *
TYP 2.05087 0.75590 2.713 0.006665 **
4.3 Quelques autres analyses 71
L’état d’infection du patient est probablement non significatif parce qu’il est correlé au fait que le patient
soit rentré en urgence. On peut le vérifier en faisant un test d’association entre les deux variables TYP et
INF.
> chisq.test(icu$TYP,icu$INF)
Comme avec lm(), on peut tracer des graphes de diagnostic à partir du résultat du modèle :
170 170
165 165
2
2
Std. deviance resid.
1
Residuals
1
0
0
−1
−1
> par(mfrow=c(2,2))
−2
−2
151
151
−3
−3
−4 −2 0 2 −3 −2 −1 0 1 2 3
165
151
1.5
Std. deviance resid.
18
Cook’s distance
1.0
172
0.5
0.0
Là encore, on peut faire d’autres graphes en utilisant les objets issus de la régression. Je vous laisse en
exercice le soin de produire un graphe donnant la prédiction du modèle pour la relation entre l’âge et la
survie, stratifiée sur les variables TYP et LOC...
72 Chapitre 4. Analyses statistiques
Fonctions analytiques
> t(bact)
1 2 3 4 5 6 7 8 9 10 11 12
time 0.00 20.50 29.00 45.00 53.00 68.50 77.00 92.50 102.50 115 125.50 140.50
conc 5.89 5.76 5.86 6.04 6.23 6.57 6.77 7.28 7.51 8 8.28 8.57
13 14 15
time 150.0 164.50 172.00
conc 8.6 8.75 8.74
Ajustons à ces données un modèle exponentiel avec retard dont la formule est donnée par :
On reprend exactement la même syntaxe que pour lm(), mais cette-fois ci le côté droit de la formule contient
l’expression mathématique de la fonction :
> expmod<-nls(conc~y0+(time>lag)*(y1-y0)*(1-exp(-k*(time-lag))),
data=bact,start=c(y0=6,y1=9,k=0.07,lag=40))
> summary(expmod)
Parameters:
Estimate Std. Error t value Pr(>|t|)
y0 5.836667 0.075450 77.359 < 2e-16 ***
y1 11.016010 1.094351 10.066 6.92e-07 ***
k 0.006960 0.002259 3.0810.0105 *
lag 42.720943 3.633768 11.757 1.44e-07 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
y1 -1.536e-08
k 1.356e-08 -0.9920
lag 5.760e-01 -0.4932 0.5521
Comme pour lm() la fonction summary() donne les estimations des paramètres et de leur erreur standard,
ainsi que l’erreur résiduelle du modèle. On a de plus une matrice des corrélations entre les paramètres.
La méthode fitted s’applique également à des objets de type nls et on peut donc l’utiliser pour tracer
l’ajustement :
8.5
8.0
> plot(bact)
7.5
conc
> lines(bact[,1],fitted(expmod))
7.0
6.5
6.0
0 50 100 150
time
On voit que l’ajustement du modèle n’est pas idéal. En fait, on peut trouver de bien meilleurs modèles
pour représenter les courbes de croissance, dont un modèle de Gompertz dont l’équation est donnée ci-
dessous
(time−Tlag )
−e1 k 1+(y
conc = ymin + (ymax − ymin ) e−e
max −ymin ) ln(10)
(4.3)
Ce modèle s’ajuste bien mieux comme le démontre le graphe ci-dessous superposant l’ajustement précé-
demment obtenu avec l’ajustement du modèle de Gompertz.
> nlmod<-nls(conc~y0+(ymax-y0)*exp(-exp(k*exp(1)*(lag-time)/
+ ((ymax-y0)*log(10))+1)),data=bact,start=c(y0=6,ymax=9,k=0.07,lag=40))
8.5
8.0
> plot(bact)
> lines(bact[,1],fitted(expmod))
7.5
conc
> plot(bact)
7.0
o Observations
Modèle exponentiel
Modèle de Gompertz
> lines(bact$time,fitted(expmod),lty=2)
6.5
> lines(bact$time,fitted(nlmod),lty=1)
> legend(110,7,legend=c("Observations",
6.0
0 50 100 150
"Modèle exponentiel","Modèle de Gompertz"),
time
+ pch="o ",lty=c(0,2,1))
F IG . 4.8 – Ajustement d’un modèle de Gompertz.
74 Chapitre 4. Analyses statistiques
Note : il n’existe pas de méthode pour tracer les graphes de diagnostic pour un objet de type nls. Exercice après la
fin de ce cours : en construire une (voir chapitre suivant pour les scripts) !
Le désavantage de la fonction nls() est qu’il faut disposer de la forme analytique de la fonction de
régression. Bien qu’on puisse développer un modèle sous forme d’équations différentielles en utilisant
le solveur d’équations différentielles de R, la librairie nls2 développée par Sylvie Huet et son équipe de
l’INRA est plus pratique et plus complète. Son seul désavantage est qu’elle n’est plus disponible sous
Splus (après avoir été développée sous Splus, elle a été portée sous R et maintenant ne tourne plus que
sous R).
Outre l’intégration d’équations différentielles, cette librairie est également précieuse pour l’estimation
de paramètres de variance (quand la fonction de variance dépend des paramètres) ou pour des méthodes
d’estimation alternatives (par exemple quand la variance empirique est connue par des répétitions).
La librairie mgcv fournit la fonction gam() et d’autres fonctions permettant d’ajuster des modèles addi-
tifs généralisés. Ces modèles sont des extensions des modèles linéaires généralisés où on peut utiliser des
fonctions lissées (splines) des prédicteurs. Comme je n’utilise jamais ces modèles je vous conseille d’aller
voir directement la documentation si vous en avez besoin...
Nous avons déjà parlé de la librairie splines qui contient les fonctions splines et des fonctions de lissage,
ainsi que de la librairie modreg() qui contient une fonction comme scatter.smooth() pour le tracé et le lissage
de nuages de points.
R dispose de fonctions permettant de construire des formules à base de chaînes de caractères. Dans la
section 4.3.1 nous avons utilisé un jeu de données comprenant une variable réponse STA et 19 variables
explicatives :
> icu[1:3,]
ID STA AGE SEX RAC SER CAN CRN INF CPR SYS HRA PRE TYP FRA PO2 PH PCO BIC CRE
1 8 0 27 2 1 1 1 1 2 1 142 88 1 2 1 1 1 1 1 1
2 12 0 59 1 1 1 1 1 1 1 112 80 2 2 1 1 1 1 1 1
3 14 0 77 1 1 2 1 1 1 1 100 70 1 1 1 1 1 1 1 1
LOC
1 1
2 1
3 1
4.3 Quelques autres analyses 75
Imaginons qu’on veuille (pour l’exemple car ça ne doit pas être très recommandé d’un point de vue statis-
tique !) construire une formule de type y∼AGE+SEX+...+LOC. On ne va pas la construire à la main, c’est
fastidieux et ça manque d’élégance. On va plutôt réutiliser la fonction paste pour concaténer des chaînes
de caractères :
> myform<-paste("STA~",paste(names(icu),sep="+",collapse="+"),sep="")
> myform
[1] "STA~ID+STA+AGE+SEX+RAC+SER+CAN+CRN+INF+CPR+SYS+HRA+PRE+TYP+FRA+PO2
+PH+PCO+BIC+CRE+LOC"
On est très fort. Une ligne de code et on a la formule. Problème : R ne la reconnaît pas comme une formule,
pour lui c’est une chaîne de caractères :
> lm(myform,data=icu)
Error in terms.default(formula, data = data) :
no terms component
Mais heureusement, il existe nos fameuses fonctions as.quelquechose, donc on va utiliser ici as.formula()
qui va dire à R de considérer la chaîne de caractères comme une formule. En utilisant une opération qui
s’appelle le "parsing", il va retrouver les éléments dont il a besoin (prédicteurs et réponse) :
> lm(as.formula(myform),data=icu)
Call:
lm(formula = as.formula(myform), data = icu)
Coefficients:
(Intercept) ID AGE SEX RAC SER
-1.1102720 -0.0002115 0.0043946 -0.0542530 0.0092494 -0.0340147
CAN CRN INF CPR SYS HRA
0.2641645 0.0362800 0.0078993 0.0633530 -0.0010216 -0.0002999
PRE TYP FRA PO2 PH PCO
0.0815575 0.2494482 0.0638819 0.0527067 0.2446313 -0.2456837
BIC CRE LOC
-0.0435981 0.0304534 0.3519416
Cette technique peut être très utile le jour où on a une série d’analyses univariées à effectuer de façon
automatique pour trouver les variables candidates pour l’analyse multivariée ultérieure.
76 Chapitre 4. Analyses statistiques
Chapitre 5
Scripts et fonctions
Jusqu’ici nous avons tapé nos commandes dans la fenêtre de commande, mais nous allons voir que
nous pouvons travailler sous un éditeur de texte pour garder une trace de nos commandes (section 5.1).
Nous verrons ensuite comment automatiser certaines de nos procédures, en utilisant des boucles pour
répéter plusieurs fois la même chose, et des tests pour simplifier le traitement des données (section 5.2).
Tout naturellement nous allons donc nous initier à ce qui fait vraiment la force d’un langage comme S, son
utilisation comme un langage de programmation. Les fonctions que nous allons voir en section 5.3 ne sont
que des extensions de tout ce que nous avons fait jusqu’à présent.
5.1 Scripts
Pour écrire un script, on ouvre un fichier texte dans son éditeur de texte favori (nedit, emacs, vi, ...) ou
pous Splus on crée un nouveau script à partir du menu déroulant. On tape les commandes dans ce fichier
exactement comme on les aurait tapées dans la ligne de commande. Par exemple, sacrifions à la tradition
immémoriale des programmeurs en faisant un script qui écrive "bonjour" :
cat("Bonjour \n") #cette instruction dit bonjour
Sauvons ce programme dans un fichier texte que nous appelerons hello.R (usuellement hello.ssc sous
Splus, ".ssc" étant l’extension reconnue comme script par Splus).
Le symbole dièse "♯" sert à insérer des commentaires : tout ce qui est écrit sur la même ligne après
ce symbole n’est pas lu par le programme. Il est VIVEMENT conseillé de commenter abondamment ses
programmes...
Nous pouvons utiliser ce fichier script simplement pour garder nos commandes en mémoire, ainsi
si nous voulons réutiliser ces commandes dans un programme ultérieur nous pourrons copier-coller à
77
78 Chapitre 5. Scripts et fonctions
partir du fichier (plusieurs lignes en même temps aussi). Sous Windows on peut aussi utiliser le bouton
d’exécution (une petite flèche) qui exécute les lignes sélectionnées avec la souris (en surbrillance).
Une fois le fichier sauvegardé, on peut également utiliser la fonction source() qui lit les commandes
dans le fichier argument. Par exemple pour utiliser notre fichier hello.R :
> source("Scripts/hello.R")
Bonjour
Un script est exécuté dans l’environnement qui l’appelle, donc il connaît les variables qui existent dans
la session de travail en cours. Imaginons un script pour tirer un échantillon aléatoire de taille n dans une
loi normale et en calculer la somme :
xcal<-rnorm(n)
print(mean(xcal))
Pour appeler ce fichier que nous appelerons meanemp.R, il va nous falloir spécifier n sinon nous aurons
un message d’erreur. Nous spécifions donc la valeur de n avant de lancer le programme, et R s’en sert.
> n<-5
> source("Scripts/meanemp.R")
[1] 0.3793601
Notez au passage qu’on a utilisé dans le programme une variable xcal. Après l’exécution, xcal est donc
créée.
> xcal
[1] -0.9088552 0.2523620 1.6302777 0.3281835 0.5948324
Note : Si xcal existait déjà avant, sa valeur est modifiée par le programme. Ici c’est un programme très simple, mais
c’est une source d’erreur fréquente d’utiliser une variable dans un fichier sourcé qui écrase une variable utilisée
dans le programme principal. Nous verrons que ce problème n’existe pas avec les fonctions.
Mode batch
où infile.R est le fichier script et outfile.txt est le fichier des résultats (optionnel, s’il n’est pas spécifié les
résultats sont écrits dans R.out). De plus, si le script crée des graphes durant son exécution, et que ces
graphes ne sont pas redirigés vers un fichier à l’aide d’une instruction comme postscript() ou jpeg(), un
fichier R.out.ps sera créé qui contiendra les graphes.
Sous Windows, c’est la commande Rcmd à la place de R :
Par défaut, l’intégralité des commandes lues dans infile.R sont affichées à l’écran et écrites dans out-
file.txt. Il est possible de ne pas les écrire ou d’en écrire seulement une partie en jouant avec la fonction
options(echo=F) qui supprime l’affichage des commandes tapées ou lues (options(echo=T) pour le réta-
blir).
Spécifier un répertoire sous Windows peut être une opération douloureuse. La première chose à savoir,
c’est que Windows est maintenant compatible avec des répertoires séparés par un "/" au lieu d’un "backs-
lash" "\". Si vous persistez à vouloir utiliser "\" (au prix d’une probable non compatibilité avec Linux ce
qui peut être gênant pour porter vos programmes ultérieurement), il faut le doubler "\\".
La deuxième chose à savoir est qu’il faut éviter les espaces dans les chemins. Je crois qu’on peut rem-
placer un espace par un tilde ou un underscore mais c’est à vérifier. L’idéal est donc un schéma du type :
>monchemin<-"monrepertoire/monsousrepertoire/monfichier"
5.2.1 Tests
Tests if
Par exemple, écrivons une instruction pour tester si une variable est positive et afficher un message dans
chaque cas :
> xcal<-3
> if(xcal>0) cat("Positif\n") else cat("Négatif\n")
Positif
> xcal<-(-4.2)
> if(xcal>0) cat("Positif\n") else cat("Négatif\n")
Négatif
Si on veut utiliser plusieurs instructions, il faut impérativement utiliser la syntaxe suivante et mettre
des accolades autour des instructions à l’intérieur de la boucle :
if (condition) {
instr1
instr2
...
} else {
instr3
...
}
80 Chapitre 5. Scripts et fonctions
> y<-x>0
> y
[1] FALSE
> if(!y) cat("Positif\n") else cat("Négatif\n")
Positif
Tests ifelse
ifelse(condition,element.si.oui,element.si.non)
L’élément condition peut être un vecteur ou une structure plus compliquée. Par exemple dans la petite
routine qui suit, on fait un tirage de 5 valeurs dans une loi normale, et on utilise une fonction ifelse() :
> x<-rnorm(5)
> x
[1] 0.5507422 0.8465560 0.1771461 -0.2824869 -2.0010691
> ifelse(x>0,x,-x)
[1] 0.5507422 0.8465560 0.1771461 0.2824869 2.0010691
Il n’aura échappé à personne qu’on aurait pu utiliser la fonction valeur absolue pour faire la même chose,
mais c’est didactique.
Tests à choix
La fonction switch() permet de choisir une action à effectuer en fonction d’un choix parmi une liste de
choix possibles :
> dist<-"Uniforme"
> switch(dist,Normale=rnorm(1),Uniforme=runif(1),Exponentielle=rexp(1))
[1] 0.9215703
Ici, switch() compare la valeur de la chaîne de caractères dist aux différentes valeurs possibles et effectue
l’instruction correspondante. S’il ne trouve pas de chaîne de caractères identiques, il ne renvoie rien.
> switch(dist,Normale=rnorm(1),Uniforme=runif(1),Exponentielle=rexp(1))
NULL
Pour utiliser la fonction switch() de manière interactive, on peut la combiner avec la fonction menu()
qui permet d’afficher une liste de choix et donne un message explicatif si on essaie un choix hors de la liste.
5.2 Tests et boucles 81
> switch(menu(c("Normale","Uniforme","Exponentielle"),
title = "Distributions possibles"),rnorm(1),runif(1),rexp(1))
Distributions possibles
1:Normale
2:Uniforme
3:Exponentielle
Selection: 4
Enter an item from the menu, or 0 to exit
Selection: 2
[1] 0.3466248
5.2.2 Boucles
Boucles for
Il y a trois types de boucles possibles sous R. La première est une boucle for, c’est-à-dire qu’on répète
une certaine opération un nombre déterminé de fois. Par exemple, imaginons qu’on veuille utiliser 3 fois
notre programme meanemp.R, on écrit :
> for (i in 1:3) source("Scripts/meanemp.R")
[1] 0.01242656
[1] 1.145393
[1] 0.297879
Arrêtons-nous un instant sur la syntaxe : tout d’abord, i est la variable ici sur laquelle se fait la boucle. En-
suite, on dit à R que i prend ses valeurs dans la séquence {1,2,3}. On aurait très bien pu écrire for (i in c(1,2,3)
ou même puisqu’ici on n’utilise pas la valeur de i en tant que telle, for (i in c("première boucle","deuxième
boucle","troisième boucle"). On aurait pu aussi vouloir appliquer notre petit script à 3 valeurs différentes
de n, par exemple :
> for (n in c(10,50,100)) source("Scripts/meanemp.R")
[1] 0.1415974
[1] -0.02527698
[1] 0.0944161
Ici, c’est le même n qui est utilisé pour faire tourner la boucle et comme paramètre de rnorm() à l’intérieur
de meanemp.R.
Si on veut utiliser plusieurs instructions, il faut impérativement utiliser la syntaxe suivante et mettre
des accolades autour des instructions à l’intérieur de la boucle :
for (var in ensemble) {
instr1
...
}
Boucles while
while (condition) {
instr1
...
}
A l’entrée dans la boucle, on évalue la valeur de la condition. Si elle est remplie on exécute la boucle puis
on reteste la condition, ainsi de suite jusqu’à ce que la condition ne soit plus remplie. Evidemment il est
possible de faire des boucles infinies si on oublie de modifier la condition ou d’ajouter un nombre de
boucles maximal. Par exemple :
> x<-1
> while(x>0) {
> cat("Si vous en avez assez, faites CTRL-C!\n")}
Si vous en avez assez, faites CTRL-C!
Si vous en avez assez, faites CTRL-C!
...
Boucles repeat
Une boucle repeat est une boucle sans condition (comme while) ni incrémentation (comme for), et dont
la syntaxe est donc :
repeat expr
Pour l’interrompre, il faut donc utiliser une instruction break depuis l’intérieur de la boucle qui inter-
rompt l’exécution de la boucle
repeat {
instr1
...
if(condition) break
5.3 Fonctions 83
instr
...
}
La boucle est répétée jusqu’à ce que condition soit remplie, ce qui interrompt l’exécution.
On utilise une boucle for quand on connaît à l’avance le nombre d’itérations. Sinon, si on veut exécuter
au moins une fois la boucle, puis tester une condition on utilise une boucle repeat, alors que si on veut
tester la condition avant d’exécuter la boucle, on préfèrera un while.
5.3 Fonctions
function(arguments) {
instr1
instr2
...
}
Bien sûr il ne faut pas oublier d’allouer la fonction à un objet qui deviendra alors une fonction que l’on
pourra appeler en lui donnant comme paramètres les arguments. Définissons une fonction pour tirer un
échantillon de taille n dans une loi normale, et appelons-la meanemp parce que dans quelques instants on
va lui demander aussi de calculer la moyenne empirique :
> meanemp<-function(n) {
+ rnorm(n)
+ }
Les "+" ont été rajouté par la fenêtre de commande lorsque j’ai rentré les lignes successives, on ne doit donc
pas les écrire dans la fonction (voir syntaxe). Pour utiliser cette nouvelle fonction :
> meanemp(6)
[1] -0.19651715 -1.59358653 -0.28999386 -0.48242600 2.06217250 0.04951092
Donc par défaut, on constate que la fonction renvoie rnorm(n) c’est-à-dire le résultat de la dernière ligne
avant l’accolade finale. De plus comme d’habitude on peut utiliser notre fonction pour l’affecter à un autre
objet :
> y<-meanemp(10)
Arguments
Une fonction peut très bien ne pas avoir d’arguments (on pourrait écrire une fonction print.coucou qui
afficherait bonjour et rendrait la main). Mais la plupart des fonctions ont besoin d’arguments, et on peut en
rentrer un nombre quelconque. Modifions notre fonction meanemp pour choisir le type de la distribution
utilisée, grâce à une instruction switch() :
> meanemp<-function(n,dist) {
+ switch(dist,Normale=rnorm(n),Uniforme=runif(n),Exponentielle=rexp(n))
+ }
> meanemp(5,"Uniforme")
[1] 0.001069471 0.126829559 0.670254293 0.476346088 0.204326755
S’il y a plusieurs arguments, pour appeler la fonction on peut soit passer les arguments dans le même
ordre que l’entête de la fonction, soit les nommer explicitement :
> meanemp(n=6,dist="Exponentielle")
[1] 1.4972355 0.1492560 2.9048288 0.1111800 1.1228182 2.4967689
On peut aussi définir des arguments par défaut. Il suffit alors de donner une valeur à l’argument consi-
déré dans l’entête de la fonction, et si l’argument en question n’est pas donné à la fonction quand on
l’appelle, il est fixé à la valeur par défaut :
> meanemp<-function(n,dist="Uniforme") {
+ switch(dist,Normale=rnorm(n),Uniforme=runif(n),Exponentielle=rexp(n))
+ }
> meanemp(4)
[1] 0.64538586 0.43161672 0.63903422 0.07145698
Lorsque la fonction qu’on a créée fait appel à d’autres fonctions comme ici, on peut passer des argu-
ments de la fonction parente aux fonctions filles (ici, rnorm, runif, et rexp par exemple) en utilisant un
argument spécial "...". Ajouter "..." dans la liste des arguments de la fonction permet d’ajouter des argu-
ments lors de l’appel de la fonction, qui seront transmises aux fonctions filles si besoin. Ici, passons par
exemple les 2 paramètres des distributions normales et uniformes :
> meanemp<-function(n,...,dist="Uniforme") {
+ switch(dist,Normale=rnorm(n,...),Uniforme=runif(n,...),Exponentielle=rexp(n,...))
+ }
> meanemp(4,0.1,0.5)
[1] 0.3137684 0.4355425 0.2522535 0.3020638
Le seul problème c’est qu’il faut mettre les arguments par défaut à la fin, sinon il prend le premier argument
"..." pour l’argument dist.
5.3 Fonctions 85
Résultats
Par défaut on l’a vu, la dernière ligne d’instructions est considérée et renvoyée comme le résultat de
la fonction. On peut explicitement renvoyer un résultat en utilisant la fonction return(). Modifions notre
fonction pour renvoyer la moyenne empirique de notre échantillon :
> meanemp<-function(n,...,dist="Uniforme") {
+ ycal<-switch(dist,Normale=rnorm(n,...),Uniforme=runif(n,...),Exponentielle=rexp(n,...)
+ return(mean(ycal))
+ }
> meanemp(4,0.1,0.5)
[1] 0.3328645
Au passage, on voit qu’ici on a défini une variable de calcul interne à la fonction, ycal. Cette variable
est créée lors du calcul et détruite à la sortie de la fonction. Si une variable du même nom existait dans le
programme principal, une copie est créée et détruite, mais la variable du programme principal est inchan-
gée.
> ycal
Error: Object "ycal" not found
De la même façon, une copie de n est créée lorsque l’on rentre dans la fonction, et si on modifie n dans la
boucle, en sortie n n’aura pas changé.
Quand on a plusieurs résultats à renvoyer, en utilisant la fonction return() on crée en fait une liste
de plusieurs éléments. On peut nommer si on le souhaite certains ou tous les éléments de cette liste. Par
exemple, modifions meanemp() pour qu’elle renvoie aussi la variance empirique, et mettons le tout dans
un objet yres :
> meanemp<-function(n,...,dist="Uniforme") {
+ ycal<-switch(dist,Normale=rnorm(n,...),Uniforme=runif(n,...),Exponentielle=rexp(n,...)
+ return(empm=mean(ycal),empv=var(ycal))
+ }
> yres<-meanemp(40,dist="Normale")
> yres
$empm
[1] 0.1131836
$empv
[1] 0.8153576
Une fonction peut s’appeler elle-même et le plus joli exemple que je connaisse est cette fonction qui
calcule factorielle de n (n! = n × (n − 1) × (n − 2) × ... × 2) :
facto<-function(n) {
if(n==1) return(1) else return(n*facto(n-1))
}
> methods(class=integer)
[1] "as.data.frame.integer" "as.integer" "is.integer"
On peut aussi regarder les classes pour lesquelles une certaine méthode existe :
> methods(residuals)
[1] "residuals.default" "residuals.glm" "residuals.HoltWinters"
[4] "residuals.isoreg" "residuals.lm" "residuals.nls"
Il est possible sous R de définir ses propres classes (par exemple, le résultat d’une analyse particulière)
et de définir des fonctions de type summary() ou plot(), qui seront associées à cette classe et appelées chaque
fois que summary() ou plot() seront appliquées à un objet de cette nouvelle classe. De telles opérations
dépassent toutefois largement le cadre de ce manuel déjà bien trop touffu et je vous conseille d’aller voir
les docs spécialisées si vous vous sentez des âmes de programmeur S.
Une fonction très utile pour estimer le temps pris par une fonction est system.time() (qui appelle
proc.time() avant et après l’exécution pour en déduire le temps passé à calculer.
Les fonctions body() et args() permettent d’afficher respectivement le corps (les instructions contenues
dans) et les arguments d’une fonction.
> args(meanemp)
function (n, ..., dist = "Uniforme")
NULL
La fonction str() permet d’afficher de façon compacte un résumé de la structure d’un objet. Le résultat
est particulièrement abscons :
Néanmoins, lors de la programmation de fonctions, cette fonction permet d’avoir accès à toute la struc-
ture interne de l’objet ce qui peut être utile pour en comprendre l’architecture et les propriétés.
Chapitre 6
Cette partie du cours a été écrite par Denis Mestivier dans le cadre de son enseignement du langage
C. Elle traite d’abord de la compilation de librairies partagées en C, puis de leur utilisation dans R. Dans
le cours de Denis, il y a aussi toute une section sur l’interface entre les langages de type HTML et des
programmes C que je n’ai pas repris ici.
Cette section a été écrite pour un système Linux avec R. Les sections 6.1 à 6.3 traitent des librairies en
C général. La partie qui nous intéresse le plus pour ce cours est la section 6.4 qui explique comment créer
des fonctions d’interface dans le programme C qui seront appelées par R, et comment passer des variables
dans les deux sens. Enfin, je reviendrai dans la section 6.5 sur la façon de créer des librairies depuis R sous
Linux (il existe une commande spéciale) et sous Windows.
87
88 Chapitre 6. Programmation avancée (Denis Mestivier)
} void hello(void)
~> gcc -c toto.c -E -o toto.e {
~> more ./toto.e int a=-5;
# 2 "joe.c" 2 printf("la valeur est : %d\n", 13 );
plein de blablabla printf("abs = %d\n", ( a<0 ? a : -a ) );
}
La seconde étape va produire un fichier dit objet, c’est-à-dire contenant du code compréhensible par la
machine mais pas encore auto-suffisant pour s’éxecuter.
La dernière étape, dite de "linkage" ou "d’édition de liens" va permettre de relier tous les morceaux de
code objets pour produire un fichier éxecutable définitif.
Cette étape est très importante car ceci signifie que l’on peut compiler des fichiers séparément puis les
assembler après. De la même facon, on peut très bien envisager de travailler sur un fichier, le recompiler
et le linker à des fichiers déjà compilés et donc accélerer la génération du code puisque tout n’est pas à
recompiler.
Deux autres intérêts de bien comprendre cette étape de "linkage" sont à souligner : 1/ pouvoir utiliser
des fonctions écrites dans un autre langage. En effet, la compilation produit des fichiers objets, quel que
soit leur langage d’origine. Et l’édition de liens assemble des fichiers objets. On comprend donc qu’il est
possible de produire différents fichiers objets, à partir de différents langages, et de les assembler pour for-
mer un même exécutable. 2/ pouvoir créer des librairies. Ces librairies renferment des objets, que l’éditeur
de liens, ou le système, va aller chercher lorsqu’il en a besoin.
Les librairies sont une collection de fonctions précompilées, donc sous forme d’objet. Il s’agit en général
de fonctions répondant à un ensemble de tâches précises, par exemple une librairie de fonctions mathéma-
tiques, ou une librairie de fonction d’alignement de séquences.
Un nom de librairie devra toujours commencer par lib, suivi du nom que l’on veut donner à la librai-
rie.
L’extension que l’on donne à la librairie peut être : .a (librairie statique) ou .so (librairie dynamique).
Nous verrons plus loin la différence entre ces deux approches.
Pour indiquer au compilateur que l’on veut utiliser une librairie, il faut rajouter l’extension -l suivi du
nom de la librairie (sans le lib) sur la ligne de compilation. Exemple :
Notre exemple de compilation séparée est très simple : une fonction qui affiche bonjour et une fonc-
tion principale (la fameuse fonction main() en C) qui l’appelle. Chaque fonction sera dans un fichier séparé.
A partir de cette situation, nous allons illustrer la compilation séparée, puis la création d’une librairie dy-
namique.
Remarquez dès maintenant le mot réservé C ’extern’ dans le fichier test.c. Nous avions vu dans les
premiers cours de programmation que lorsque le compilateur arrive à l’appel d’une fonction, celle-ci doit
être déjà déclarée pour être utilisée. Il y avait alors deux situations : ou bien le corps de cette fonction était
avant son appel et le compilateur n’avait pas le problème de ’reconnaître’ la fonction au moment de son
appel, ou bien on introduisait le prototype de la fonction en tout début de programme pour renseigner le
compilateur sur la structure de cette fonction, si bien que lors de son appel, il peut vérifier la compatibilité
des types passés.
Mais dans les deux cas de figures, le corps de la fonction était dans le même fichier à compiler.
Coment utiliser une fonction lorsque le corps de cette fonction se trouve dans un autre fichier. C’est le
but de l’instruction ’extern’ : elle renseigne le compilateur sur la structure de la fonction (puisque l’on
donne le prototype de la fonction) et elle indique également que le corps de la fonction est à l’exterieur et
donc de reporter à l’étape d’édition de liens le problème de trouver les corps de la fonction.
Ces deux fichiers objets étants crées, appelons l’éditeur de liens (en fait gcc le fait pour nous) afin de
les réunir dans un même éxecutable :
90 Chapitre 6. Programmation avancée (Denis Mestivier)
Voilà, tout simplement. On aurait aussi pû compiler et faire l’édition de liens en même temps (comme
dans le cas d’un seul programme où toutes ces étapes sont transparentes pour l’utilisateur) :
Mais la première solution était pour bien différencier les étapes impliquées.
L’instruction ’extern’ permet également de déclarer des variables dans un fichier et de les utiliser dans
un autre fichier. Bien entendu, normalement on passe la variable par la fonction, de façon à se conforter à
l’idée de boite noire.
Pour qu’une variable soit visible entre deux fichiers, il faut qu’elle soit globale, c’est-à-dire déclarée en
dehors de toute fonction, généralement en début de fichier.
Voici un exemple de variable globale rajoutée dans le main() :
/* test.c :
* appelle la fonction de test void main(void)
*/ {
a=5;
#include <stdio.h> printf("avant hello(), a vaut %d\n",
#include <stdlib.h> a );
hello();
/* prototypage */ printf("apres hello(), a vaut %d\n",
extern int hello(void); a );
int a; }
Pour utiliser la variable a dans le fichier hello.c, il faut déclarer que cette variable sera utilisée dans
le fichier, mais qu’elle est déclarée à l’extérieur du fichier :
/* extern int a;
* hello.c : contient une fonction
* test qui affiche "bonjour" void hello( void )
*/ {
printf("Test reussi !\n");
#include <stdio.h> printf("Dans hello(), a=%d\n", a );
}
6.3 Le print "coucou" de la compilation séparée 91
Maintenant cette façon de procéder est à prohiber sauf si vous savez vraiment ce que vous faites. C’est
une hérésie à la notion de boite noire, car une modification dans un fichier entraîne des répercutions dans
un autre fichier ! ! !
Par exemple, introduisons simplement une ligne dans le fichier hello.c :
Vous pouvez constater que dans la fonction main() la valeur de a est modifiée ! Evidente comme erreur
sur cet exemple simple, cela devient inextricable lors de longs programmes, découpés en plusieurs fichiers.
Vous voilà prévenus...
Comme je ne veux pas trop insister sur les librairies statiques, voici simplement un exemple, les pages
de manuels sont là pour répondre à vos questions éventuelles.
Créons maintenant une librairie statique, appelée libAGM2.a contenant notre fonction :
Pour voir quelles sont les fonctions qui sont contenues dans notre librairie :
~> nm libAGM2.a
hello.o:
00000000 t gcc2_compiled.
00000000 T hello
U printf
et maintenant pour faire l’édition de liens entre la fonction contenue dans la librairie libAGM2.a et notre
programme principal main() dans test.c, voici la ligne de compilation :
Dans un système de librairies statiques, quand on compile plusieurs programmes qui utilisent la même
fonction, on duplique cette portion code dans le code exécutable, et donc en mémoire lors de l’exécution,
ce qui peut finir par occuper beaucoup de place disque et de place mémoire.
Dans un système de librairies partagées, une portion de code n’est pas inclu dans l’exécutable, mais
sera indexée d’une certaine manière (ceci est géré par le système). Lors de l’exécution, le système sait
où aller chercher cette portion de code. Si l’on doit recharger cette portion lors de l’exécution d’un autre
programme, ce système va vérifier que cette portion de code n’est pas déjà indexée et dans ce cas faire en
sorte de partager la partie de code entre les applications.
Ceci présente aussi l’interêt de ne pas inclure le code dans le programme et donc si on veut changer
une librairie sans avoir à recompiler le reste du programme, cela ne pose pas de problèmes.
L’utilisation est un peu plus complexe. Il faut d’abord compiler les fichiers objets à inclure dans la
librairie en indiquant une option au compilateur (option -shared) puis réunir ces fichiers objets dans la
librairie, toujours avec l’option -shared :
Enfin, viens l’édition de liens avec cette librairie partagée avec nos fonctions :
Le système ne sait pas où trouver la librairie partagée. Par défaut, il la cherche dans certains réper-
toires (indiqués dans /etc/ld.so.conf) et il faut donc utiliser une variable d’environnement spéciale pour
renseigner le système : LD_LIBRARY_PATH :
Maintenant, je peux faire des modifications dans hello(). Par exemple, voici la nouvelle version de ma
fonction :
/*
* hello.c : fichier contenant une fonction test
* qui affiche "bonjour"
*/
#include <stdio.h>
Nous pouvons ainsi constater qu’il n’a pas été utile de recompiler le reste du programme !
6.4 C et R
Nous allons maintenant voir comment utiliser nos fonctions C (avec toujours notre print "coucou")
dans l’environnement R. Puis nous verrons comment passer les différents types de données entre C et R.
Nous allons maintenant charger (loader) la librairie libAGM2.so dans R pour pouvoir utiliser la fonction
hello(). Trois instructions R sont à connaître :
• dyn.load() : pour charger la librairie... dynamique
94 Chapitre 6. Programmation avancée (Denis Mestivier)
> dyn.load("libAGM2.so")
> is.loaded("john")
[1] FALSE
> is.loaded("hello")
[1] TRUE
> .C("hello")
Test reussi - nouvelle version !
list()
>
Voilà, tout simplement ! On n’a passé aucun argument à la fonction hello() et cette fonction ne nous à
retourné aucun résultat. Nous verrons ceci plus loin.
Les arguments passés à la fonction C, au niveau de cette fonction, sont des adresses ! ! ! Rappelez-vous
que lorsque l’on appelle la fonction C à partir de R via la fonction .C(), les objets passés à cette fonction sont
copiés et c’est l’adresse de cette copie qui est transmise à la fonction.
Vous avez maintenant compris le principe, ce qui suit est un ensemble d’exemples pour montrer com-
ment passer des valeurs, et c’est surtout une affaire de pointeurs en C.
Nous pouvons maintenant tout simplement manipuler notre variable dans la fonction C et récupérer
les modifications dans R. Voici une nouvelle fonction :
l’on peut décider de ne conserver que le premier élément (ici l’argument 1, et le seul de notre fonction !).
Mais on peut aussi donner un nom à l’argument lors de l’appel par .C() et utiliser ce nom. Voici les deux
exemples :
Maintenant que vous avez compris que l’on passe des pointeurs et qu’un tableau n’est qu’un pointeur
en C, le reste est assez simple.
Voici une nouvelle fonction que l’on ajoute à testInt.c :
Bien sûr, on peut modifier le tableau dans la fonction et récupérer ces modifications sous R.
Voici la fonction précédente modifiée :
Merci à Fred.
En R, les chaînes de caractères sont codées comme des tableaux de chaînes, mais s’il y a une seule
chaîne, donc ce sont des char **.
La fonction C est la suivante :
Sous R, un tableau est codé, comme en C, sous forme linéaire, c’est–à–dire que les lignes (ou les co-
lonnes) sont mises bout à bout. On passera donc l’adresse du début, soit un pointeur.
En C, comme on ne recevra qu’un pointeur sur la première case, il faudra calculer la position de la case
(i, j). Cette position, pour une matrice M de taille n × m, est donnée par la formule M [j + m ∗ i].
Voici la fonction en C :
Dans ce que l’on a vu précédemment, la façon dont les variables sont passées entre R et C introduit
quelques subtilités. Les revoici : passage uniquement par pointeurs, les vecteurs et les tableaux sont en
pointeurs simples, les chaînes de caractères sont en pointeurs doubles.
Or, il n’est pas question de modifier les prototypes de nos fonctions pour faire plaisir à R. C’est le but
des fonctions d’interfaçage, écrites en C, qui vont être les fonctions appelées par R via .C() et les vraies
fonctions C.
Ces fonctions, par convention, vont porter le nom de la fonction C suivi de _R. Elles seront introduites dans le même
fichier que celui où se trouvent les fonctions à interfacer.
Par exemple, imaginons que l’on ait une fonction qui accepte deux valeurs et qui retourne leur somme,
typiquement :
Comme avec l’appel de R on ne peut pas utiliser de fonctions qui retournent une valeur, et que l’on
passe uniquement des pointeurs, on va devoir écrire une fonction d’interfaçage. Cette fonction récupèrera
les informations de R et s’occupera d’appeler correctement la fonction add() précédente.
6.4 C et R 99
Rappelons l’idée centrale : ne pas modifier nos fonctions déjà écrites car elles nous servent pour d’autres
occasions (interfaçage avec python ?) mais écrire une toute petite fonction qui fera le lien entre ce que nous
impose R et notre fonction.
Lorsque R passe un tableau M d’entiers de taille L × C, on doit voir cela comme L par C cases alignées
en mémoire.
Lorsque l’on crée un tel tableau en C, on commence par créer un vecteur de L cases, chacune contenant
un pointeur sur un entier. Puis on crée L vecteurs de C cases d’entiers et on assigne à M [i] l’adresse du
vecteur i.
Il manque donc un tableau entre la représentation R et le codage C. Voici donc l’interfaçage (notez que
l’on modifie la matrice durant l’affichage. C’est idiot en théorie, mais dans le cas présent, nous poursuivons
un but pédagogique) :
/* Fonction C classique }
*/
void taby( int **m, int lig, int col ) /* Fonction d’interfaçage entre taby() et R
{ */
int i, j;
void taby_R( int *m, int *lig, int *col )
for( i=0 ; i<lig ; i++ ) {
{ int i;
for( j=0 ; j<col ; j++ ) int **k=(int **)calloc(*lig,sizeof(int *));
{
printf("[%d]", m[i][j] ); for( i=0 ; i<*lig ; i++ )
m[i][j] *= 10; k[i] = &m[i*(*lig)];
}
printf("\n"); taby( k, *lig, *col);
} }
et sous R :
[1] 10 20 30 40 50 60 70 80 90 [1,] 10 40 70
> w=matrix(w,3,3) [2,] 20 50 80
> w [3,] 30 60 90
[,1] [,2] [,3] >
6.5 Compilation de librairies dynamiques sous R et Splus 101
Sous C
m=(int **)calloc( lig, sizeof(int *))
lig=3
Col=3
m[1][2]
Interfacage :
Le cours de Denis montre comment créer des librairies partagées en général. Pour R et Splus, il existe
des instructions particulières utilisant la commande R (Rcmd pour Windows, Splus,...) permettant de gé-
nérer des librairies destinées à ces programmes.
Linux
Il existe une instruction permettant de compiler une librairie partagée pour R. On peut l’appeler depuis
une session R en utilisant la fonction system() qui permet d’exécuter des commandes du shell depuis une
session de travail. L’exemple ci-dessous montre la compilation du programme rsaem.c en une librairie
partagée libSAEM.so :
Windows
Normalement il devrait être possible de lancer la compilation depuis la fenêtre de commande en faisant
un appel à DOS depuis R, mais je n’ai pas réussi à faire fonctionner le système (je soupçonne un problème
de PATH). En pratique la façon la plus simple de procéder consiste donc à compiler le fichier depuis une
fenêtre d’exécution MS-DOS par la commande :
Si l’exécutable Rcmd n’est pas reconnu il faut déclarer le chemin de R/bin dans l’environnement utilisateur.
Ensuite le chargement et l’utilisation de la librairie se font comme sous Linux.
Linux
Sous Splus on utilise également une compilation en ligne de commande pour créer une librairie du
nom de S.so (le nom peut être changé, cf doc).
Windows
Avant de compiler, il faut modifier le programme source (ici, rsaem.c) pour ajouter avant chaque fonc-
tion appelée dans Splus le mot-clé suivant : "__declspec(dllexport)".
> createChapter(".")
> makeChapter(".")
> dyn.open("S.dll")
Il semble de plus qu’il faille disposer d’un compilateur C/C++ pour que ces commandes fonctionnent.
6.6 Librairies 103
6.6 Librairies
> library()
Packages in library ’/usr/local/lib/R/library’:
Les fonctions contenues dans une librairie donnée peuvent être listées, avec une brève description, en
tapant library(help=nomdelalibrairie).
On charge une librairie par la commande library(nomdelalibrairie). Par exemple pour charger nlme :
> library(nlme)
Loading required package: lattice
Loading required package: grid
> data(package=nlme)
Data sets in package ’nlme’:
A l’installation des librairies, les pages d’aide correspondantes sont disponibles et on peut donc obtenir
par help(). De plus sur le site où on peut télécharger les librairies, il y a en général une documentation
104 Chapitre 6. Programmation avancée (Denis Mestivier)
succinte sur l’usage de la fonction, plus les exemples qui sont présentés dans la librairie. En général ça
suffit pour démarrer... Bon courage !
Bibliographie
[1] S-PLUS User’s Guide, Version 6.0. Data analysis division, MathSoft, Seattle, WA, 2000.
[2] M. Baumgartner. Une introduction à S-Plus. Ecole polytechnique fédérale de Lausanne, 1994.
[3] A. Bruce and H. Gao. Applied wavelet analysis with S-PLUS. Springer-Verlag, New York, 1996.
[4] J. Chambers and T. Hastie. Statistical models in S. Chapman & Hall, London, 1993.
[5] D. Chessel and J. Thioulouse. Introduction au logiciel S-Plus. DEA Analyse et Modélisation des Sys-
tèmes Biologiques - Université Lyon 1, 1999.
[6] L. Ferrara and D. Guégan. Analyser les séries chronologiques avec S-Plus. Une approche paramétrique.
Presses Universitaires de Rennes, 2002.
[7] S. Huet, A. Bouvier, M. Gruet, and E. Jolivet. Statistical tools for nonlinear regression. Springer-Verlag,
New York, 1996.
[8] S. Kaluzny, S. Vega, and C. Cardos. S-PLUS spatial stats. User’s manual for Windows and Unix. Springer-
Verlag, New York, 1998.
[9] A. Krause and M. Olson. The basics of S and S-PLUS. Springer-Verlag, New York, 1997.
[10] J. Pinheiro and D. Bates. Mixed-effect models in S and S-PLUS. Springer-Verlag, New York, 2000.
[11] B. Ripley. Introductory guide to S-Plus. University of Oxford, 1994.
[12] W. Venables and B. Ripley. Modern applied statistics with S-PLUS. Springer-Verlag, New York, 1994.
[13] W. Venables and B. Ripley. S programming. Springer-Verlag, New York, 2000.
[14] E. Zinot and J. Wang. Modeling financial time series with S-Plus. Springer-Verlag, New York, 2003.
105
Index
106
INDEX 107
cat(), 30 floor(), 19
cbind(), 24 for, 81
ceiling(), 19 formula(), 75
chisq.test(), 61 friedman.test(), 61
chol(), 26 function(), 83
choose(), 19 gamma(), 19
coefficients(), 65 hist(), 48, 49
contour(), 48 identify(), 45
cor.test(), 61 if, 79
cos(), 19 ifelse(), 80
cumprod(), 26 is.data.frame(), 37
cumsum(), 26 is.na(), 30
data(), 40, 103 jpeg(), 56
data.frame(), 32 kruskal.test(), 61
dbeta(), 59 ks.test(), 61
dbinom(), 59 lapply(), 38
dchisq(), 59 legend(), 45
det(), 26 length(), 26
detach(), 34 library(), 103
dev.off(), 56 lines(), 45
dexp(), 59 list(), 35
df(), 59 lm(), 63
dgamma(), 59 locator(), 45
dgeom(), 59 log(), 19
dhyper(), 59 log10(), 19
diag(), 26 logb(), 19
dim(), 26, 34 lower.tri(), 26
dimnames(), 32 lowess(), 52
dlnorm(), 59 ls(), 14
dlogis(), 59 ls.print(), 69
dnbinom(), 59 lsfit(), 69
dnorm(), 58, 59 main(), 86
dpois(), 59 mantelhaen.test(), 61
dunif(), 59 matplot(), 48
dweibull(), 59 matrix(), 23
eigen(), 26 max(), 57
exp(), 19 mcnemar.test(), 61
factor(), 26, 28 mean(), 57
fisher.test(), 61 median(), 57
108 INDEX
menu(), 80 rev(), 26
methods(), 86 rm(), 14
min(), 57 scan(), 39
mtext(), 45 segments(), 45
names(), 34 seq(), 20
ncol(), 26 shapiro.test(), 61
nrow(), 26 sin(), 19
options(), 79 solve(), 26
order(), 26, 27 solve.qr(), 26
outer(), 51 sort(), 26
pairs(), 48 source(), 78
par(), 54–55 spline(), 52
paste(), 32, 75 sum(), 26
persp(), 48, 51 summary(), 57
pie(), 48, 51 svd(), 26
plot(), 43 switch(), 80
options de plot(), 44 system(), 101
png(), 56 system.time(), 86
points(), 45 t(), 26
poly(), 69 t.test(), 59, 61
polygon(), 45 tan(), 19
postscript(), 56 tapply(), 38
print(), 30 text(), 45
proc.time(), 86 title(), 45
prod(), 26 trunc(), 19
prop.test(), 61 tsplot(), 48
qqline(), 50 unique(), 26, 27
qqnorm(), 48, 50 unlist(), 36
qqplot(), 48, 50 update(), 68
qr(), 26 upper.tri(), 26
quantile(), 57 var(), 57
rainbow(), 51 var.test(), 61
rank(), 26, 28 vector(), 35
rbind(), 24 while, 82
read.table(), 39 wilcox.test(), 61
rect(), 45 write(), 40
rep(), 20 write.table(), 40
repeat, 82 Fonctions mathématiques, 19
return(), 85 Format graphiques
INDEX 109
Quitter
q(), 15
Tests
expressions logiques, 19
if(), 79
ifelse(), 80
switch(), 80
sélection par, 22
Variables
convention de noms, 18
LETTERS(), 31
letters(), 31
month.abb(), 31
month.name(), 31
opérateur d’affectation, 18
référencer un élément d’un data.frame, 33
référencer un élément d’un vecteur, 21
référencer un élément d’une liste, 35
référencer un élément d’une matrice, 25
structures, 17
types, 17
valeurs manquantes, 29