Vous êtes sur la page 1sur 110

Manuel R/S-Plus 13 novembre 2008

R et Splus

Cours et manuel de référence à l’usage des débutants

Emmanuelle Comets

Avec l’aimable participation de Denis Mestivier

Adresse : INSERM U738


Université Paris 7
UFR de Médecine site Bichat
16 rue Henri Huchard
75 018 Paris
Courrier électronique : emmanuelle.comets@inserm.fr
2
Table des matières

Table des matières 2

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

2.2.4 Sélection d’éléments dans une matrice . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25


2.2.5 Algèbre matricielle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
2.2.6 Fonctions usuelles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.3 Quelques points importants au sujet des variables . . . . . . . . . . . . . . . . . . . . . . . . . 28
2.3.1 La règle du recyclage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
2.3.2 Valeurs manquantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
2.3.3 Affichage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
2.4 Autres objets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
2.4.1 Chaînes de caractères . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
2.4.2 Objet de type data.frame . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
2.4.3 Objet de type liste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
2.4.4 Quelques remarques générales sur les objets . . . . . . . . . . . . . . . . . . . . . . . . 37
2.4.5 Fonctions apply . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
2.5 Fichiers de données . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
2.5.1 Lecture de fichiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
2.5.2 Ecriture de fichiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

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

4.3.1 Modèles linéaires généralisés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70


4.3.2 La régression non linéaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
4.3.3 Modèles additifs généralisés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
4.3.4 La régression non paramétrique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
4.3.5 Construction de formules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74

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

6 Programmation avancée (Denis Mestivier) 87


6.1 Compilation : les différentes étapes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
6.2 Les librairies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
6.3 Le print "coucou" de la compilation séparée . . . . . . . . . . . . . . . . . . . . . . . . . 89
6.3.1 Les fichiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
6.3.2 Compilation séparée . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
6.3.3 Les variables globales et externes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
6.3.4 Création d’une librairie statique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
6.3.5 Librairie partagée . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
6.4 C et R . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
6.4.1 Chargement de la librairie dans R . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
6.4.2 Et maintenant les subtilités . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
6.4.3 Passer des arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
6.4.4 Fonction d’interfaçage sous R . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
6.4.5 interfaçage pour un tableau 2D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
6.5 Compilation de librairies dynamiques sous R et Splus . . . . . . . . . . . . . . . . . . . . . . . 101
6.5.1 Compilation sous R . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
6.5.2 Compilation sous Splus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
6.6 Librairies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
6 TABLE DES MATIÈRES

6.6.1 Obtention de librairies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103


6.6.2 Utilisation de librairies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103

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...

1.1 Présentation du langage S

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.

1.1.1 Pourquoi utiliser S

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 Présentation du système

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 Eléments importants

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

C’est là que l’on tape les commandes, en réponse à l’invite :


>

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

Fenêtre d’écriture de scripts

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

Sous Linux, place aux purs et durs.


On ne dispose pas d’interface graphique sophistiquée, mais seulement de la ligne de commande et
d’une fenêtre Motif qui s’ouvre pour les graphes. D’un autre côté, comme on dispose de toute la puissance
de Linux pour visualiser ses fichiers de commande, pour organiser son travail dans des sous-répertoires,
pour lancer des opérations de manière non interactive (mode batch, voir section 5.1.2), que la compilation
de librairies partagées et l’écriture de programmes shell permettant de combiner la puissance de plusieurs
logiciels dans la même analyse est très facile, et que de toutes façons, on peut tout faire par la ligne de
commande, on ne voit vraiment pas en quoi on a besoin d’un tas de gadgets pour adeptes du "Point and
click".

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 :

Nom : le nom de la fonction et à quelle librairie elle appartient.

Description : une brève description de l’usage de la fonction.


1.4 Documentation 13

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.

F IG . 1.1 : Exemple de l’aide en ligne sous R.

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.

1.4.2 Autres sources d’aide

Livres

Les livres disponibles au département sont les suivants :


• la documentation de Splus version [1]
14 Chapitre 1. Premiers pas en S

• le livre de Chambers et Hastie, très complet pour débuter [4]


• les deux livres de Venables et Ripley, qui sont des références en eux-mêmes [12, 13] et le guide d’in-
troduction à Splus de Ripley [11]
• le livre de Pinheiro et Bates, Mixed-effects models in S and S-plus [10]
• le livre de Huet et al. sur la librairie nls2, Statistical tools for nonlinear regression [7]
• plusieurs autres livres plus spécialisés [3, 6, 8, 9, 14]

Sites Internet

Le site de R : http ://www.r-project.org/


Le site de Splus : http ://www.insightful.com/products/splus/
Les news :
• R:
http ://cran.r-project.org/doc/Rnews/
• Splus :
http ://lib.stat.cmu.edu/s-news/
aussi disponibles sur http ://www.biostat.wustl.edu/s-news/

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/

1.5 Organiser son travail

1.5.1 Gestion des objets

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()

Les mêmes options sont disponibles que pour ls().


1.5 Organiser son travail 15

1.5.2 Gestion des projets

Sauvegarde d’une session

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()
>

Je n’ai pas trouvé d’équivalent sous Splus.

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 :

F IG . 1.2 : Changement du répertoire de démarrage de R.

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

2.1.1 Types de variables et conventions

Il y a plusieurs types de variables définies sous R :

• variables numériques : entiers, réels.

• variables alphanumériques : chaînes de caractères.

• variables catégorielles : facteurs, booléens (vrai/faux).

A partir de ces types de base, on peut créer des structures :

• ensemble de variables du même type : vecteurs, matrices, tableaux.

• objets composites : data.frame, listes.

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

TAB . 2.1 : Exemples de noms de variables possibles et impossibles.

2.1.2 Créer des variables : l’opérateur d’affectation

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

On peut créer plusieurs variables de même valeur d’un coup :

> 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é.

On peut afficher la valeur d’une variable simplement en tapant son nom :

> x
[1] 3

Cela vaut pour tous les objets définis dans R.

2.1.3 Utilisation de la fenêtre de commande comme une calculette

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

Pour élever x à la puissance n, on écrit soit x∧ n soit x**n :

> 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.

log(), log10() logarithme népérien, logarithme en base 10


logb(x,b) logarithme en base b (compatible Splus)
exp() exponentielle
abs() valeur absolue
trunc() troncature (trunc(1.2) donne 1, trunc(-1.2) donne -1)
floor(), ceiling() troncature (floor(1.2) donne 1, floor(-1.2) donne -2)
sin(), cos(),... fonctions trigonométriques
asin(), acos(), .. fonctions trigonométriques inverses
choose() coefficients Cnp
beta(), gamma(), ... fonctions spéciales (Γ, beta,...)

TAB . 2.2 : Quelques fonctions numériques opérant sur des variables.


On peut écrire plusieurs instructions sur une même ligne en les séparant par un point-virgule :

> x<-3;y<-x**2;y
[1] 9

2.1.4 Expressions logiques

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).

2.2 Vecteurs et matrices

2.2.1 Outils de création d’un vecteur


L’instruction de base pour créer un vecteur est la fonction c().

> myvec<-c(3,4.1,8.6)
> myvec
[1] 3.0 4.1 8.6

Plusieurs fonctions spécialisées permettent de créer des vecteurs :


• générer une séquence régulière : seq(from=a,to=b,by=pas). Cette fonction crée une séquence de a à b
par pas de pas. Si l’argument pas est omis, on peut aussi utiliser la forme équivalente a : b qui va de
a à b par pas de 1 (d’autres options existent, voir doc).
• générer des réplications : rep(x,times=n,each=m). Cette fonction crée un nouveau vecteur répétant n
fois le vecteur formé par la répétition m fois de chaque élément de x. On utilise souvent la forme par
défaut rep(x,n), qui répète n fois la totalité du vecteur x (même chose que rep(x,times=n)).
Exemple d’utilisation de seq() :

> 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

Exemple d’utilisation de rep() :

> 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

2.2.2 Manipulation de vecteurs

Appliquer une fonction à un vecteur

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

Ceci est équivalent à :

> 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

Ici, on a testé quels éléments de myvec étaient positifs.

Référencer un vecteur

On référence le ième élément d’un vecteur vec par vec[i].

> vec[2]
[1] 0.1

Sélectionner des éléments d’un vecteur

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

pour avoir seulement tous les éléments supérieurs à 0.3.


Du coup plus rien ne nous empêche de travailler sur certains éléments du vecteur :

> 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

Exclusion d’éléments d’un vecteur

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).

2.2.3 Création d’une matrice ou d’un tableau

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

NA est le symbole dénotant des valeurs manquantes (voir plus loin).


Une autre façon de construire des matrices est d’utiliser les instructions cbind() et rbind() sur des vec-
teurs ou des matrices. Avec cbind() on colle des colonnes et avec rbind() des lignes :

> 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

> cbind(vec1,mat1) [,1] [,2] [,3]


vec1 vec1 1 2 3
[1,] 1 4 5 6 4 5 6
[2,] 2 7 8 9 7 8 9
[3,] 3 10 11 12 10 11 12
> rbind(vec1,mat1)

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.

2.2.4 Sélection d’éléments dans une matrice


On fait référence à l’élément i,j de la matrice mymat par mymat[i,j] :

> 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

2.2.5 Algèbre matricielle

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

[,1] [,2] [,3]


[1,] 1 2 3
[2,] 4 5 6
> b
[,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 5 6 7 8
[3,] 9 10 11 12
> a%*%b
[,1] [,2] [,3] [,4]
[1,] 38 44 50 56
[2,] 83 98 113 128

Note : Si a et b sont des vecteurs, a%*%b donne leur produit scalaire.

Il existe aussi un certain nombre de fonctions applicables aux matrices, résumées dans la table 2.3.

diag() créer des matrices diagonales


upper.tri(), lower.tri() créer des matrices triangulaires supérieures ou inférieures
t() transposée
det() déterminant d’une matrice
eigen() valeurs propres
qr(), chol() décomposition QR, décomposition de Cholevsky
svd() décomposition en valeurs propres
solve(), solve.qr(), inverse d’une fonction
backsolve()

TAB . 2.3 : Fonctions d’algèbre matricielles.

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.

Note 3 : upper.tri() et lower.tri() n’existent pas en Splus.

2.2.6 Fonctions usuelles

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

length() donne le nombre d’éléments


ncol(), nrow() donne le nombre de colonnes et rangées d’une matrice
dim() donne les dimensions
sort() trie un vecteur (options disponibles)
rank(), order(), rev() donne le rang et ordre
factor() transforme l’argument en un facteur (données catégorielles)
unique() ôte les réplications
sum(), prod() calcule la somme et le produit de tous les éléments
cumsum(), cumprod() calcule la somme cumulative et le produit cumulatif

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

2.3 Quelques points importants au sujet des variables

2.3.1 La règle du recyclage


Prenez le message d’erreur suivant :

> 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).

Exemple d’addition entre un vecteur et une matrice :

> 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

2.3.2 Valeurs manquantes


Les valeurs manquantes sont codées indifféremment par la valeur NA (Not Assigned) ou NaN (Not A
Number). Exemple :

> 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.

> cat("Vecteur :",miss,"\n")


Vecteur : 1 6 NA 4

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

2.4 Autres objets

2.4.1 Chaînes de caractères

Variable chaîne de caractères

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 :

> machaine<-"Ceci est une chaine"


> machaine
[1] "Ceci est une chaine"

On peut donc comme pour des nombres en faire des vecteurs et appeler un élément du vecteur :

> vecstr<-c("Ceci est une chaine","Ceci est une autre chaine")


> vecstr[2]
[1] "Ceci est une autre chaine"

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"

Chaînes de caractères spéciales

Il y a des chaînes particulières définies sous forme de constantes (dans R) :


• LETTERS : les 26 lettres de l’alphabet, en majuscules ;
• letters : les 26 lettres de l’alphabet, en minuscules ;
• month.name : le nom des 12 mois de l’année (en anglais) ;
• month.abb : la même chose, abrégé en 3 lettres.
On peut donc les utiliser comme suit :

> 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

Manipulation de chaînes de caractères

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="".

> paste("V",1:5,sep="",collapse=" ")


[1] "V1 V2 V3 V4 V5"

Ici, on a collé toutes les chaînes créées dans une seule en les séparant par un blanc.

2.4.2 Objet de type data.frame

Création d’objet de type data.frame

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

> mydf<- data.frame(matmis)


> dimnames(mydf)[[2]]<-c("col1","col2","col3")
> mydf
col1 col2 col3
1 1 NA 1
2 6 5 2
3 NA 2 3
4 4 3 4

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"

On peut utiliser le résultat de attributes() :


34 Chapitre 2. Données et variables

> 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"

Fonctions attach() et detach()

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

R ne connait pas patient seul, il connait seulement essai$patient.


Quand on veut s’affranchir de ce nom encombrant, on peut utiliser la fonction attach() :

> attach(essai)
> patient
[1] Patient 1 Patient 2 Patient 3
Levels: Patient 1 Patient 2 Patient 3

Maintenant on peut faire référence à patient seul.

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.

Pour rendre le data.frame à l’anonymat :

> detach(essai)
2.4 Autres objets 35

2.4.3 Objet de type liste

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 :

> courses<-list(c("carottes","1 kg"),c("pommes","Elstar","2 kg"),


autres=c("produit vaisselle","petit"),budget=30)
> courses
[[1]]
[1] "carottes" "1 kg"

[[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)

"carottes" "1 kg" "pommes" "Elstar"


autres1 autres2 budget
"2 kg" "produit vaisselle" "petit" "30"

Néanmoins malgré ces difficultés conceptuelles les listes sont un outil puissant et très flexible.

Utilisation de listes par des fonctions

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.

2.4.4 Quelques remarques générales sur les objets

Pour tout type d’objet de R, il existe en général :


• une fonction testant si une variable est un objet de ce type : le nom est en général is.type()
• une fonction de coercition qui transforme la variable en un objet de ce type, si c’est possible : le nom
est en général as.type()
Exemple :

> 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

On peut transformer un booléen en un entier en utilisant la fonction as.integer() :

> 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

2.4.5 Fonctions apply

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.

> xlist<-as.list(1:5) [[2]]


> xlist [1] 1.414214
[[1]]
[1] 1 [[3]]
[1] 1.732051
[[2]]
[1] 2 [[4]]
... [1] 2
> lapply(xlist,sqrt)
[[1]] [[5]]
[1] 1 [1] 2.236068

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.

> xmat<-matrix(1:4,ncol=2) [1,] 10 30


> xlist<-list(xmat,xmat*10,xmat*100) [2,] 20 40
> xlist
[[1]] [[3]]
[,1] [,2] [,1] [,2]
[1,] 1 3 [1,] 100 300
[2,] 2 4 [2,] 200 400

[[2]] > xfac<-rep(c(1:4),3)


[,1] [,2] > xfac
2.5 Fichiers de données 39

[1] 1 2 3 4 1 2 3 4 1 2 3 4 > unlist(xlist)


> tapply(unlist(xlist),xfac,sum) [1] 1 2 3 4 10 20 30 40
1 2 3 4 100 200 300 400
111 222 333 444

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.

2.5 Fichiers de données

2.5.1 Lecture de fichiers


La fonction la plus souple pour lire des données est scan(). La version de base est :

>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 :

Error in scan("attenu.dat", skip = 1) : "scan" expected a real, got "c168"

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

• nrows=n : lit n lignes du fichier ;


• header=F ou T : si T, lit la première ligne du fichier et s’en sert comme noms pour les colonnes ;
• 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).
Enfin, on peut avoir accès à des fichiers de données disponibles dans la base de données R. Il suffit pour
ça de taper data(nomdujeudedonnees). Cela permet d’avoir des bases de données sur lesquelles essayer
des fonctions.

> 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.

2.5.2 Ecriture de fichiers


Les fonctions scan() et read.table() ont leur contrepartie pour écrire des fichiers, les fonctions write() et
write.table(). Pour write(), il faut préciser le nombre de colonnes. Une option très importante est l’option
append=T/F : si T, R écrit à la suite du fichier sans écraser le début, si F, il efface le fichier et le réecrit.

> 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.

3.1 Fonctions graphiques

3.1.1 Créer et modifier un graphe

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

F IG . 3.1 – Graphe simple de cos(x) pour x∈[0,4π].

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

et on obtient le même graphe que la figure précédente.


Note : la fonction plot() est une méthode. Le résultat de son application dépend du type d’objet auquel on l’applique.
Par exemple ici, on a vu qu’elle pouvait recevoir 2 vecteurs ou bien une matrice et que dans les deux cas elle
va traiter l’objet différemment (voir aussi section 5.3.3 et un exemple en section 4.2.4 où nous l’appliquerons
au résultat d’une régression linéaire).

Options

Les options les plus importantes de la fonction plot() sont données dans le tableau 3.1 :

main="Le titre" donner un titre au graphe


sub="Le sous-titre" donner un sous-titre au graphe (en dessous de l’axe des X)
xlab="Légende X",ylab spécifier la légende des axes
xlim=c(xa,xb), ylim=c(ya,yb) fixer les limites des axes
axes=T/F tracer les axes (F : ne pas les tracer)
type="" par défaut vaut "p" pour points
(les autres valeurs possibles sont décrites plus loin)
log="" échelle logarithmique
("x"=axe des X en log, "y"=axe des Y en log, "xy"=les 2)
pch=n,lty=n change le symbole ou le type de ligne utilisé
col=n ajoute de la couleur
font=n,cex=n change la fonte et la taille du texte et des symboles

TAB . 3.1 : Options les plus utilisées de la fonction plot().

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

sub="intervalle 0-4 pi",


Cos(X)

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

F IG . 3.2 – Graphe avec options.

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

type="o" type="h" >plot(x1,y1,type="l",main="type=\"l\"")


1.0

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

F IG . 3.3 – Graphes pour différentes valeurs de type.

Ajouter des éléments à un graphe

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

title(),axis() ajouter un titre ou un axe


legend() ajouter une légende
text() ajouter du texte
mtext() ajouter du texte dans la marge
box() entourer le graphe d’un cadre
segments(a,b,c,d) ajouter un trait entre (a,b) et (c,d)
lines(x,y) ajouter un trait entre x(=c(a,b)) et y(=c(c,d))
points(a,b) tracer un point aux coordonnées (a,b)
arrows(a,b,c,d) tracer une flèche (a,b) et (c,d)
rect(a,b,c,d) tracer un rectangle
polygon(x,y) tracer un polygone
abline() ajouter une ligne de pente et intercept spécifié (voir syntaxe)
identify() trouver les coordonnées d’un point sur une courbe
locator() trouver les coordonnées d’un point en cliquant avec la souris

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

F IG . 3.4 – Graphe de cos(x) et sin(x).

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

légende, et les options importantes de cette fonction sont les suivantes :


• lty : donne le type de la ligne à tracer pour chaque élément de la légende, soit sous forme d’un seul
chiffre, soit sous forme d’un vecteur de la même taille que le texte (ou -1 pour pas de ligne).
• pch : donne le type de symbole à tracer pour chaque élément de la légende (mêmes remarques que
pour lty).
• col : donne la couleur à utiliser pour chaque élément de la légende (mêmes remarques que pour lty).
Note : sous Splus il faut utiliser marks au lieu de pch pour spécifier des symboles différents.

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

F IG . 3.5 – Graphe de cos(x) et sin(x), avec légende.

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

F IG . 3.6 – Graphe de cos(x) et sin(x), suite.

3.1.2 Types de graphes

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

TAB . 3.3 : Principales formes de graphes.

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

5 10 15 20 25 30 35 50 100 150 200 250 300

F IG . 3.7 – Corrélations entre paramètres estimés.

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

F IG . 3.8 – Histogramme d’un échantillon aléatoire


tiré dans une loi normale.

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

F IG . 3.9 – Boîte à moustache de deux échantillons


aléatoires.

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

> for(i in 1:length(xtim)) {


Data

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

F IG . 3.10 – Boîte à moustache des observations en


fonction du temps.

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 :

Normal Q−Q Plot


3
2
1

> xgaus<-rnorm(500)
Sample Quantiles

> qqnorm(xgaus)
0

> qqline(xgaus)
−1
−2

−3 −2 −1 0 1 2 3

Theoretical Quantiles

F IG . 3.11 – QQ-plot d’un échantillon aléatoire gaus-


sien.

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

Montrons maintenant un exemple d’utilisation de la fonction pie(). On trace un camembert où chaque


part est égale. Notez l’usage de la fonction rainbow() qui donne un vecteur contenant un nombre donné de
couleurs différentes.

4 3

5 2

> pie(rep(1,12),
6 1

col=rainbow(12),radius = 0.9)

7 12

8 11

9 10

F IG . 3.12 – Exemple d’utilisation de pie().

Note : La fonction rainbow() n’existe pas sous Splus.

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

F IG . 3.13 – Exemple d’utilisation de persp().

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.

3.1.3 Interpolation et lissage

Fonctions polynômiales et interpolation

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

F IG . 3.14 – Lissage par lowess().


L’utilisation de techniques de lissage est très utile pour visualiser les relations pouvant exister entre des
données.

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

F IG . 3.15 – Lissage par splines.

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é.

Autres fonctions de lissage

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

F IG . 3.16 – Interpolation par loess().


Notez au passage la façon dont on a demandé l’ajustement loess(). Il s’agit de ce que R appelle une
formule, et nous allons la retrouver dans le prochain chapitre car c’est la forme sous laquelle on va spécifier
toutes les analyses statistiques.
La fonction associée predict.loess() permet de prédire la réponse pour un vecteur de la variable indé-
pendante étant donné le résultat d’un ajustement préalable avec loess(). Optionnellement, on peut égale-
ment calculer l’erreur standard associée. On utilise predict.loess() de la même façon que les autres fonctions
predict (voir le chapitre sur la régression linéaire).
54 Chapitre 3. Graphes

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]

F IG . 3.17 – Lissage par scatter.smooth().

3.2 Environnement graphique

3.2.1 Principales options graphiques

Contrôle de l’environnement graphique

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

F IG . 3.18 – Superposition de deux graphes.

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.

Tracer plusieurs graphes différents sur la même page

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.

3.2.2 Sauver un graphe dans un fichier


On peut exporter des graphes dans un fichier selon plusieurs formats. Le plus courant est le format
postscript qui est un langage vectoriel utilisé pour expliquer aux imprimantes les objets à imprimer. En
plus d’être compact, c’est un format très pratique car on peut modifier la taille des graphiques par exemple
pour les inclure dans des rapports ou des présentations. Quand on veut créer un fichier graphique sous R,
on ouvre un fichier graphique par la fonction postscript() en lui donnant un nom, on tape les commandes
pour créer le graphe, puis on ferme le fichier graphique par la fonction dev.off(). Par exemple, pour créer la
56 Chapitre 3. Graphes

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.

4.1 Statistiques descriptives

4.1.1 Fonctions de base


Pour obtenir les statistiques de base d’un jeu de données, on peut utiliser la fonction summary().
Lorsque cette fonction est appliquée à un vecteur ou à une matrice, elle renvoie un vecteur composé de
la valeur minimale, la valeur correspondant au quantile 5%, la médiane, la moyenne, la valeur correspon-
dant au quantile 95% et la valeur maximale.

> 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

mean() calcul de la moyenne


median() calcul de la médiane
min() valeur la plus basse
max() valeur la plus haute
var() variance
quantile() quantiles des données (par défaut, donne
les quantiles à 0%,25%,50%,75% et 100%)
var() variance

TAB . 4.1 : Fonctions permettant d’obtenir des statistiques descriptives.

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" .

4.1.2 Distributions statistiques

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

• rnorm() : échantillon aléatoire de taille n tiré dans la loi normale N (µ, σ)

> 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

Le tableau 4.2 liste les principales distributions disponibles dans le logiciel.


Note 1 : Sous Splus la paramétrisation de dgamma() utilise le paramètre rate=1/β (qui peut aussi être spécifié sous
R pour compatibilité entre les deux programmes).
Note 2 : Splus dispose de la fonction dmvnorm() pour la loi normale multivariée. Sous R, la librairie MASS contient
une fonction mvrnorm() pour échantillonner une loi multivariée normale.

4.1.3 Tests statistiques


R dispose aussi d’un grand nombre de tests statistiques. On peut par exemple effectuer un test T sur la
moyenne de deux échantillons avec la fonction t.test :

> x1<-rnorm(20,2)
> x2<-rnorm(20)
> t.test(x1,x2)

Welch Two Sample t-test

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

Nom Distribution Paramètres par défaut Equation de la densité


(x − µ)2

dnorm() normale N (µ = 0, σ = 1) √1 e 2σ 2
2πσ
(ln(x) − µ)2

dlnorm() log-normale LN (µ = 0, σ = 1) √ 1
e 2σ 2
2πσx
1
dunif() uniforme U(a = 0, b = 1)
b−a
x−α
)
dlogis() Logistique L(α, β) 1
β e−( β 1
−( x−α ) 2
(1+e β )
λ
dpois() Poisson P (λ) λ e− x

dexp() Exponentielle E(λ = 1) λ e−λ x

dgeom() Géométrique G(p) p (1 − p)x


x γ
dweibull() Weibull W(γ, β) γ
β ( βx )(γ−1) e−( β )

dbinom() binômiale B(n, p) Cnx px (1 − p)(n−x)

Γ(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

(†) Γ(n) désigne la fonction Gamma.

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 tableau 4.3 liste les principales distributions disponibles dans le logiciel.

t.test() Test de Student pour l’égalité des moyennes


wilcox.test() Test des rangs de Wilcoxon (non paramétrique)
var.test() Test de Fisher pour l’égalité des variances
prop.test() Test de proportions
binom.test() Test pour le paramètre p d’une loi de Bernouilli
cor.test() Test d’association (Pearson, Kendall ou Spearman)
kruskal.test() Test des rangs de Kruskal-Wallis
chisq.test() Test du χ2 pour les tables de contingence
fisher.test() Test de Fisher d’indépendance dans les tables de contingence
mantelhaen.test() Test de Mantel-Haenszel pour les tables de contingence
mcnemar.test() Test du χ2 de McNemar
friedman.test() Test de Friedman pour une analyse factorielle en blocs
shapiro.test() Test de Shapiro-Wilkes pour la normalité d’une distribution
ks.test() Test de Kolmogorov-Smirnov pour la forme d’une distribution

TAB . 4.3 : Principaux tests statistiques disponibles dans R.

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 La régression linéaire

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

speed > plot(cars)


F IG . 4.1 – Jeu de données cars de R.

Ce jeu de données semble être un assez bon candidat à une régression linéaire.

4.2.2 Modèle statistique

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

lm(formula = dist ~ speed, data = cars)


Coefficients:
(Intercept) speed
-17.579 3.932

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

L’élément df.residual donne le nombre de degrés de liberté après ajustement :


> y$df.residual
[1] 48

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

F IG . 4.2 – Régression linéaire de cars.

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

Residual standard error: 15.38 on 48 degrees of freedom


Multiple R-Squared: 0.6511, Adjusted R-squared: 0.6438
F-statistic: 89.57 on 1 and 48 DF, p-value: 1.490e-12
4.2 La régression linéaire 65

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 !

4.2.4 Graphes de diagnostic

Graphes par défaut

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

Traçons ces graphiques pour notre régression précédente.

Residuals vs Fitted Normal Q−Q plot

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

Fitted values Obs. number

F IG . 4.3 – Graphes de diagnostic par défaut.

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

xlab="Valeurs prédites, échelle log",


ylab="Résidus pondérés")
0

Warning message:
2 x values <= 0 omitted from
−20

logarithmic plot in:


20 40 60 80
xy.coords(x, y, xlabel, ylabel, log)
Valeurs prédites, échelle log
> abline(h=0)
F IG . 4.4 – Un graphe de diagnostic personnalisé.
4.2 La régression linéaire 67

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

F IG . 4.5 – Tracé de la ligne de régression avec


abline().
Les options de abline() et les différentes façons de l’utiliser sont détaillées dans la documentation.

4.2.5 Evaluation et modification du modèle statistique

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

Model 1: dist ~ speed - 1


Model 2: dist ~ speed
Res.Df RSS Df Sum of Sq F Pr(>F)
1 49 12953.8
2 48 11353.5 1 1600.3 6.7655 0.01232 *
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

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)

L’interaction entre deux termes se note " :" :

> 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

Residual standard error: 15.18 on 47 degrees of freedom


Multiple R-Squared: 0.6673, Adjusted R-squared: 0.6532
F-statistic: 47.14 on 2 and 47 DF, p-value: 5.852e-12

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.

4.2.6 Autres fonctions de régression


La fonction lsfit() est une autre fonction qui permet d’effectuer une régression linéaire par régression
des moindres carrés (éventuellement pondérés). La syntaxe est différente de celle de lm et ne permet qu’une
régression univariée :

> 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

Estimate Std.Err t-value Pr(>|t|)


Intercept -17.5791 6.7584 -2.6011 0.0123
X 3.9324 0.4155 9.4640 0.0000

4.3 Quelques autres analyses

4.3.1 Modèles linéaires généralisés

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

LOC 1.80222 0.51347 3.510 0.000448 ***


INF 0.41807 0.43082 0.970 0.331846
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

Null deviance: 200.16 on 199 degrees of freedom


Residual deviance: 150.08 on 195 degrees of freedom
AIC: 160.08

Number of Fisher Scoring iterations: 4

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)

Pearson’s Chi-squared test with Yates’ continuity correction

data: icu$TYP and icu$INF


X-squared = 4.8156, df = 1, p-value = 0.0282

Comme avec lm(), on peut tracer des graphes de diagnostic à partir du résultat du modèle :

Residuals vs Fitted Normal Q−Q plot


3

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

Predicted values Theoretical Quantiles


> plot(model1)

Scale−Location plot Cook’s distance plot


170 151
0.00 0.05 0.10 0.15 0.20 0.25

165
151
1.5
Std. deviance resid.

18
Cook’s distance
1.0

172
0.5
0.0

−4 −2 0 2 0 50 100 150 200

Predicted values Obs. number

F IG . 4.6 – Graphes de diagnostic par défaut de glm().

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

4.3.2 La régression non linéaire

Fonctions analytiques

Jusqu’ici on a vu la régression lorsqu’une fonction linéaire des prédicteurs existait, éventuellement


après transformation. La fonction nls() est utilisée pour ajuster un modèle de régression lorsque la fonction
de régression n’est pas linéaire.
A titre d’exemple, on a un jeu de données de croissance bactérienne (conc) en en fonction du temps
(time), baptisé bact :

> 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 :

ymin + (ymax − ymin ) e−k(time − Tlag ) pour time > Tlag


(
conc = (4.2)
ymin pour time ≤ Tlag

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)

Formula: conc ~ y0 + (time > lag) * (y1 - y0) * (1 - exp(-k * (time -


lag)))

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

Residual standard error: 0.1307 on 11 degrees of freedom

Correlation of Parameter Estimates:


y0 y1 k
4.3 Quelques autres analyses 73

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

F IG . 4.7 – Ajustement d’un modèle non linéaire à


bact.

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) !

Fonctions définies par des équations différentielles

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).

4.3.3 Modèles additifs généralisés

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...

4.3.4 La régression non paramétrique

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.

4.3.5 Construction de formules

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

Un script est simplement un ensemble de commandes R réunies dans un fichier texte.

5.1.1 Ecriture de 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...

5.1.2 Exécution de scripts

Exécution dans le cours de la session

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

Notez bien les guillemets autour du nom du programme.


Note : Chez moi les programmes ont été stockés dans un sous-répertoire Scripts pour leur éviter d’encombrer le
répertoire où j’écris ce manuel, d’où le chemin donné en argument.

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

Sous Linux, l’exécution se fait depuis le shell par la commande :

R BATCH infile.R outfile.txt

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 :

Rcmd BATCH infile.R outfile.txt


5.2 Tests et boucles 79

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).

5.1.3 Note concernant les chemins sous Windows

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 Tests et boucles

5.2.1 Tests

Tests if

La syntaxe générale d’une instruction if est :

if (condition) expression1 else expression2

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

L’indentation n’est là que pour rendre ce schéma plus lisible.


L’élément condition est en fait un booléen, donc on peut aussi utiliser une variable de type booléen. A
titre de rappel, l’inverse (condition non remplie) s’écrit !condition.

> y<-x>0
> y
[1] FALSE
> if(!y) cat("Positif\n") else cat("Négatif\n")
Positif

Tests ifelse

La syntaxe de cette fonction est :

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
...
}

ensemble peut être une variable de type vecteur d’indices.


Note : remarquons au passage qu’il est tout à fait possible d’imbriquer plusieurs boucles for, ainsi que d’autres types
de boucles ou de tests.
82 Chapitre 5. Scripts et fonctions

Boucles while

La boucle while est une boucle de syntaxe :

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!
...

On peut plus sérieusement s’en servir pour remplir un vecteur de valeurs :

> myvec<-c();ctest<-1 1: 5.8


> while(ctest>0) { Read 1 items
+ cat("Tapez un nombre Tapez un nombre (fin : nombre négatif)
(fin : nombre négatif) \n") 1: 2.7
+ ctest<-scan("",nmax=1) Read 1 items
+ if(ctest>0) myvec<-c(myvec,ctest)} Tapez un nombre (fin : nombre négatif)
Tapez un nombre (fin : nombre négatif) 1: -2
1: 4.1 Read 1 items
Read 1 items > myvec
Tapez un nombre (fin : nombre négatif) [1] 4.1 5.8 2.7

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.

Choix du type de boucle

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

5.3.1 Ecriture de fonctions


En fait depuis qu’on a commencé à écrire des instructions qui ne tenaient plus sur une ligne, on a
commencé à faire un peu de programmation. Il suffit de rajouter la fonction function() pour y être tout à
fait. La syntaxe de la définition d’une fonction est :

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)

Et maintenant y contient un échantillon de taille 10.


84 Chapitre 5. Scripts et fonctions

5.3.2 Arguments et résultats

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))
}

Ne pas oublier le test pour vérifier qu’on atteint 1 !


86 Chapitre 5. Scripts et fonctions

5.3.3 Méthodes et fonctions : la programmation orientée objet


Come on l’a vu tout au long de ce manuel, S est un langage orienté objet qui applique des méthodes à
des classes d’objet. Une méthode comme print() donne des résultats différents selon qu’elle est appliquée à
un vecteur, un tableau ou un résultat d’analyse glm. Il est possible de voir les méthodes définies pour une
classe d’objet donnée avec la fonction methods() :

> 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.

5.3.4 Autres fonctions utiles

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 :

> matmis > str(matmis)


col1 col2 col3 num [1:4, 1:3] 1 6 NA 4 NA 5 2 3 1 2 ...
[1,] 1 NA 1 - attr(*, "dimnames")=List of 2
[2,] 6 5 2 ..$ : NULL
[3,] NA 2 3 ..$ : chr [1:3] "col1" "col2" "col3"
[4,] 4 3 4

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

Programmation avancée (Denis Mestivier)

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.

6.1 Compilation : les différentes étapes

L’étape de compilation se décompose en trois phases :


1. pré-compilation
2. compilation
3. édition de liens (linkage)
Lors de la première étape, toutes les constantes et les macros, ainsi que les headers sont inclus dans le
fichier source (on parle d’expansion).
On peut le voir en utilisant le flag -E du compilateur :

~> cat toto.c void hello(void)


#include <stdio.h> {
int a=-5;
#define VALEUR 13 printf("la valeur est : %d\n",
#define abs(x) ( x<0 ? x : -x ) VALEUR );
printf("abs = %d\n", abs(a) );

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.

6.2 Les librairies

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 :

~> gcc -o TEST test.c -lAGM2

pour faire appel à la librairie libAGM2.a.


Si la librairie ne se trouve dans dans un chemin standard, il faut indiquer au compilateur où trouver
cette dernière (flag -L) :

~> gcc -o TOTO toto.c -lMestiv -L/home/mestiv/Lib


6.3 Le print "coucou" de la compilation séparée 89

6.3 Le print "coucou" de la compilation séparée

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.

6.3.1 Les fichiers

/* * test.c : appelle la fonction de test


* hello.c : contient une fonction */
* test qui affiche "bonjour"
*/ #include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
/* prototypage */
void hello( void ) extern int hello(void);
{
printf("Test reussi !\n"); void main(void)
} {
hello();
/* }

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.

6.3.2 Compilation séparée

~> gcc -c hello.c


~> gcc -c test.c

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)

~> gcc -o Test test.o hello.o


~> ./Test
Test reussi !

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) :

~> gcc -o Test test.c hello.c


~> ./Test
Test reussi !

Mais la première solution était pour bien différencier les étapes impliquées.

6.3.3 Les variables globales et externes

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

L’exécution de ce programme donne :

~> gcc -o Test test.o hello.o Test reussi !


~> ./Test Dans hello(), a=5
avant hello(), a vaut 5 apres hello(), a vaut 5

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 :

/* hello.c : contient une fonction


* test qui ne fait qu’afficher void hello( void )
* "bonjour" {
*/ printf("Test reussi !\n");
printf("Dans hello(), a=%d\n", a );
#include <stdio.h> a=99; /* ouuilllleeeeeeuuuuuuuuuuxxxxx!!!!!
}
extern int a;

L’exécution de ce programme donne :

~> gcc -o Test test.o hello.o


~> ./Test
avant hello(), a vaut 5
Test reussi !
Dans hello(), a=5
apres hello(), a vaut 99

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...

6.3.4 Création d’une librairie statique

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 :

~> gcc -c hello.c


~> ar crv libAGM2.a hello.o
a - hello.o
~> ranlib libAGM2.a
92 Chapitre 6. Programmation avancée (Denis Mestivier)

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 :

~> gcc -o Test test.c -lAGM2 -L.


~> ./Test
Test reussi !

6.3.5 Librairie partagée

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 :

~> gcc -c -shared hello.c


~> gcc -o libAGM2.so hello.o -shared

Enfin, viens l’édition de liens avec cette librairie partagée avec nos fonctions :

~> gcc -c test.c


~> gcc -o Test test.o -lAGM2 -L.
~> ./Test
./Test: error while loading shared libraries: libAGM2.so: cannot
load shared object file: No such file or directory
6.4 C et R 93

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 :

~> export LD_LIBRARY_PATH=$LB_LIBRARY_PATH:.


~> ./Test
Test reussi !

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>

void hello( void )


{
printf("Test reussi - nouvelle version !\n");
}

Si je recompile ma librairie et seulement elle, voici les commandes :

~> gcc -c -shared hello.c


~> gcc -o libAGM2.so hello.o -shared
~> ./Test
Test reussi - nouvelle version !

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.

6.4.1 Chargement de la librairie dans 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)

• .C() : pour exécuter une fonction C dans une librairie


• is.loaded() : pour vérifier l’existence d’une fonction chargée par dyn.load()
Voici les instructions sous R :

> 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.

6.4.2 Et maintenant les subtilités

Deux points sont à noter :


1. la fonction appelée par .C() sous R ne doit pas retourner de valeurs ! Ceci est un peu ennuyant dans
les cas où une fonction doit retourner une valeur. Nous verrons avec l’interfaçage et l’encapsulation
comment il faudra contourner ce problème.
2. lorsque l’on fait appel à une fonction par .C(), les objets passés en argument sont copiés. De même,
lors du retour de cette fonction, les objets sont à nouveau copiés pour être mis dans une liste.

6.4.3 Passer des arguments

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.

Passage d’un entier

Voici notre nouvelle fonction et notre nouveau fichier.

~> cat testInt.c passage d’un entier


/* testint.c : test de librairie */
partagee avec R
6.4 C et R 95

#include <stdio.h> [blabla]


> dyn.load("libAGM2.so")
void testint( int *a ) > a = 54
{ > .C("hello")
printf("Test reussi : %d!\n", *a); Test reussi !
} list()
~> gcc -c -shared hello.c > .C("testint", as.integer(a))
~> gcc -c -shared testInt.c Test reussi : 54!
~> gcc -shared -o libAGM2.so hello.o [[1]]
testInt.o [1] 54
~> R

Modification d’une variable

Nous pouvons maintenant tout simplement manipuler notre variable dans la fonction C et récupérer
les modifications dans R. Voici une nouvelle fonction :

~> cat testInt.c }


/* testint.c : test de librairie ~> gcc -c -shared testInt.c
partagee avec R ~> gcc -shared -o libAGM2.so hello.o
passage d’un entier testInt.o
*/ ~> R
[blabla]
#include <stdio.h> > dyn.load("libAGM2.so")
> a = 54
void testint( int *a ) > .C("testint", as.integer(a))
{ Test reussi : 54!
printf("Test reussi : %d!\n", *a); [[1]]
} [1] 54

void modint( int *a ) > .C("modint", as.integer(a))


{ Je vais modifier la variable : 54
printf("Je vais modifier la Voici la nouvelle valeur : 99
variable : %d\n", *a); [[1]]
*a = 99; [1] 99
printf("Voici la nouvelle >
valeur : %d\n", *a);

Nous pouvons constater deux points :


1. la valeur est bien modifiée sous C (ce qui ne nous étonne pas trop) ;
2. la valeur modifiée est récupérable sous R.
Pour cela, il faut se rappeller qu’au retour de l’appel de la fonction .C(), tous les arguments sont copiés
et mis sous forme de liste. Dans l’exemple qui précède, cette liste est affichée juste après le retour, mais
96 Chapitre 6. Programmation avancée (Denis Mestivier)

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 :

> dyn.load("libAGM2.so") >


> a = 54 > a=54
> > a = .C("modint", z=as.integer(a))$z
> l = .C("modint", as.integer(a)) Je vais modifier la variable : 54
Je vais modifier la variable : 54 Voici la nouvelle valeur : 99
Voici la nouvelle valeur : 99 > a
> l [1] 99
[[1]] >
[1] 99

Passage d’un vecteur

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 :

~> cat testInt.c ~> R


[blabla : debut de testInt.c] > dyn.load("libAGM2.so")
void testvector( double *w, int *a ) > w = seq(1,5,1)
{ > w
int i; [1] 1 2 3 4 5
> .C("testvector", as.double(w),
for( i=0 ; i<*a ; i++ ) as.integer(length(w)))
{ 0 1.000000
printf("%d %lf\n", i, w[i] ); 1 2.000000
} 2 3.000000
} 3 4.000000
~> gcc -c -shared testInt.c 4 5.000000
~> gcc -shared -o libAGM2.so hello.o [[1]]
testInt.o [1] 1 2 3 4 5

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 :

> cat testInt.c


for( i=0 ; i<*a ; i++ )
[blabla] {
void testvector( double *w, int *a ) printf("%d %lf\n", i, w[i] );
{ w[i] *= 10.0;
int i;
6.4 C et R 97

} > w = .C("testvector", as.double(w),


} as.integer(length(w)))[[1]]
~> gcc -c -shared testInt.c 0 1.000000
~> gcc -shared -o libAGM2.so hello.o 1 2.000000
testInt.o 2 3.000000
~> R 3 4.000000
> dyn.load("libAGM2.so") 4 5.000000
> w = seq(1,5,1) > w
> w [1] 10 20 30 40 50
[1] 1 2 3 4 5 >

Passage d’une chaîne de caractères

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 :

~> cat testInt.c ~> R


[blabla] > dyn.load("libAGM2.so")
void testchar( char **s, int *a ) > w = "bonjour"
{ > w
int i; [1] "bonjour"
> .C("testchar", as.character(w),
for( i=0 ; i<*a ; i++ ) as.integer(1) )
printf("Chaine %d : %s", i, s[i] ); Chaine 0 : bonjour[[1]]
} [1] "bonjour"
~> gcc -c -shared testInt.c
~> gcc -shared -o libAGM2.so hello.o [[2]]
testInt.o [1] 1

Passage d’un tableau

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 :

~> more testInt.c {


[blabla] int i, j;
void testtab( int *m, int *lig,
int *col ) printf("Nlignes : %d\n", *lig );
98 Chapitre 6. Programmation avancée (Denis Mestivier)

printf("Ncols. : %d\n", *col ); Ncols. : 3


[1][4][7]
for( i=0 ; i<*lig ; i++ ) [2][5][8]
{ [3][6][9]
for( j=0 ; j<*col ; j++ ) [[1]]
printf("[%d]", m[j+ i*(*lig)]); [1] 1 2 3 4 5 6 7 8 9
printf("\n");
} [[2]]
} [1] 3
~> gcc -c -shared testInt.c
~> gcc -shared -o libAGM2.so hello.o [[3]]
testInt.o [1] 3
~> R > w
> dyn.load("libAGM2.so") [,1] [,2] [,3]
> w = matrix(seq(1:9),3,3) [1,] 1 4 7
> .C("testtab", as.integer(w), [2,] 2 5 8
as.integer(3),as.integer(3)) [3,] 3 6 9
Nlignes : 3

6.4.4 Fonction d’interfaçage sous R

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 :

int add(int a, int b)


{
return a+b;
}

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

void add_R( int *a, int *b, int *res)


{
*res = add( *a, *b );
}

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.

6.4.5 interfaçage pour un tableau 2D

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 :

> dyn.load("libHello.so") [1][2][3]


> w = matrix(seq(1:9),3,3) [4][5][6]
> w=.C("taby_R", as.integer(w), [7][8][9]
as.integer(3),as.integer(3))[[1]] > w
100 Chapitre 6. Programmation avancée (Denis Mestivier)

[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

Voici un diagramme pour résumer ce que l’on vient de dire :

Sous C
m=(int **)calloc( lig, sizeof(int *))
lig=3

m[0] = (int* )calloc( col, sizeof(int))

m[1] = (int* )calloc( col, sizeof(int))

m[2] = (int* )calloc( col, sizeof(int))

Col=3

m[1][2]

Sous R w = matrix( seq(1:9), 3,3 )

lig * col cases

Interfacage :

k = (int **)calloc( lig, sizeof(int *))


lig=3 for( i=0 ; i<*lig ; i++ )
k[i] = &( m[i*(*lig)]

F IG . 6.1 : interfaçage entre un tableau R et C

6.5 Compilation de librairies dynamiques sous R et Splus

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.

6.5.1 Compilation sous R

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 :

> system("R CMD SHLIB -o libSAEM.so rsaem.c ")


gcc -shared -L/usr/local/lib -o libSAEM.so rsaem.o
102 Chapitre 6. Programmation avancée (Denis Mestivier)

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 :

Rcmd SHLIB -o libSAEM.dll rsaem.c

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.

6.5.2 Compilation sous Splus

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).

>system("Splus CHAPTER rsaem.c")


>system("Splus make")
> dyn.open("S.so")

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)".

En-tête normal En-tête pour utilisation dans Splus

void saem_R(long *aseed, __declspec(dllexport) void saem_R(long *aseed,


int *nconst, int *nconst,
double *tps,double *parpop, double *tps,double *parpop,
int *numrun,double *loglik) int *numrun,double *loglik)

La compilation se fait ensuite par les commandes createChapter et makeChapter :

> 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

6.6.1 Obtention de librairies

Pour R : site du CRAN, pour la France le miroir est à Toulouse


http ://mirrors.toulouse.inra.fr/R/ et il faut cliquer sur le lien contributed packages (la façon
d’installer les librairies est décrite dans le manuel sur le site).
Pour Splus : la StatLib à l’adresse http ://lib.stat.cmu.edu/S/

6.6.2 Utilisation de librairies


La liste des librairies avec une brève description peut être obtenue par la commande library(). Par
exemple chez moi :

> library()
Packages in library ’/usr/local/lib/R/library’:

base The R base package


boot Bootstrap R (S-Plus) Functions (Canty)
CGIwithR CGI Programming in R
class Functions for classification
cluster Functions for clustering (by Rousseeuw et al.)
...

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

On note qu’il faut au préalable charger deux autres librairies.


Pour savoir quels jeux de données sont disponibles dans une librairie donnée, on peut utiliser la fonc-
tion data() avec l’option :

> data(package=nlme)
Data sets in package ’nlme’:

Alfalfa Split-Plot Experiment on Varieties of Alfalfa


Assay Bioassay on Cell Culture Plate
bdf Language scores
...

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

Affichage Loi géométrique, voir dgeom()


cat(), 30 Loi hypergéométrique, voir dhyper()
général, 18 Loi log-normale, voir dlnorm()
print(), 30 Loi logistique, voir dlogis()
Aide Loi normale, voir dnorm()
help(), 12 Loi uniforme, voir dunif()
tutoriels, 14 Loi Weibull, voir dweibull()
Analyses
Fonctions
modèle
%*%, 25
as.formula(), 75
abline(), 45, 47, 67
formula(), 75
abs(), 19
update(), 68
acos(), 19
modèles additifs généralisés
anova(), 68
gam(), 74
aov(), 68
régression linéaire
array(), 24
lm(), 63
arrows(), 45
lsfit(), 69
as.data.frame(), 37
régression linéaire généralisée
as.formula(), 75
glm(), 70
as.integer(), 37
régression logistique, voir glm()
asin(), 19
régression non linéaire
atan(), 19
nls(), 72
attach(), 34
nls2(), 74
attributes(), 33, 63
Distributions statistiques axis(), 45
Loi Beta, voir dbeta() backsolve(), 26
Loi binômiale, voir dbinom() barplot(), 48
Loi binômiale négative, voir dnbinom() beta(), 19
Loi de Poisson, voir dpois() binom.test(), 61
Loi du χ2 , voir dchisq() body(), 86
Loi exponentielle, voir dexp() box(), 45
Loi F, voir df() boxplot(), 48, 49
Loi gamma, voir dgamma() c(), 20

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

JPEG, voir jpeg() plot.cox.zph(), 62


PNG, voir png() survdiff(), 62
postscript, voir postscript() survobrien(), 62
ts
Gestion d’une session de travail
Box.test(), 62
ls(), 14
jeux de données
options(), 79
data(), 103
rm(), 14
library(), 103
system(), 101
Graphes
Méthodes
boîte à moustaches, voir boxplot()
anova
camembert, voir pie()
anova.lm(), 68
corrélations entre colonnes d’une matrice, voir
méthode générique, 68
matplot(),pairs()
plot
couleurs, voir rainbow(), par()
méthode générique, 43
fonction générique, voir plot()
plot.lm(), 66
graphes 3D, voir persp()
predict
histogramme, voir hist()
predict.lm(), 66
principaux types de graphes, 48
predict.loess(), 53
QQ-plots, voir qqplot()
print
Librairies méthode générique, 30
MASS print.glm(), 71
mvrnorm(), 59 residuals
ctest, voir t.test(), wilcox.test,... residuals.lm(), 66
power.prop.test(), 62 summary
power.t.test(), 62 méthode générique, 57
mgcv summary.lm(), 64
gam(), 74
modreg, 53 Programmation
loess(), 53 boucles, 81
predict.loess(), 53 fonctions
scatter.smooth(), 54 args(), 86
smooth.spline(), 52 body(), 86
nls2 function(), 83
nls2(), 74 methods(), 86
splines, 53 temps CPU
bs(), 53 proc.time(), 86
ns(), 53 system.time(), 86
survival tests, 79
110 INDEX

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

Vous aimerez peut-être aussi