Permalink
Switch branches/tags
Find file
Fetching contributors…
Cannot retrieve contributors at this time
6090 lines (4633 sloc) 204 KB
\documentclass[a4paper,10pt,twoside,francais]{report}
\usepackage{babel}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{varioref}
\usepackage{fancybox}
\usepackage{fancyhdr}
\usepackage{fancyvrb}
\usepackage{lineno}
\usepackage{mparhack}
\usepackage{indentfirst}
\usepackage{makeidx}
\usepackage[nottoc]{tocbibind}
\usepackage{vmargin}
\usepackage{verbatim}
\usepackage{xspace}
\usepackage{graphicx}
\usepackage{picinpar}
\usepackage[sf,bf]{titlesec}
\usepackage{listings}
\usepackage{calc}
\usepackage[colorlinks=true,urlcolor=blue,pdfpagelabels]{hyperref}
\usepackage{ctable}
\usepackage{amsmath}
\usepackage{pifont}
\usepackage{lmodern}
\usepackage{epstopdf}
\definecolor{grisclair}{rgb}{0.97,0.97,0.97}
\definecolor{grisinterm}{rgb}{0.95,0.95,0.95}
\definecolor{grisfonce}{rgb}{0.5,0.5,0.5}
\definecolor{inputcol}{rgb}{0,0,0.5}
\definecolor{outputcol}{rgb}{0.5,0,0}
\FrenchFootnotes
\AddThinSpaceBeforeFootnotes
\VerbatimFootnotes
\vrefwarning
\makeindex
%%%% COMMANDES
\newcommand{\R}{\textsf{R}\xspace}
\newcommand{\rgrs}{\textsf{rgrs}\xspace}
\newcommand{\questionr}{\textsf{questionr}\xspace}
\newcommand{\margpar}[1]{\mbox{}\marginpar{\raggedright \hspace{0pt}\small\textit{#1}}}
\newcommand{\margrs}{\margpar{\rgrs}}
\newcommand{\marqr}{\margpar{\questionr}}
\newcommand{\rfunc}[1]{\texttt{#1}\index{#1@\texttt{#1}}}
%%%% ENVIRONNEMENTS
%\newenvironment{astuce}{\paragraph{\large \ding{'355} \normalsize}}{}
\newsavebox{\fcolbox}
\newenvironment{greyframe}%
{\setlength\fboxsep{10pt}%
\setlength{\rightmargin}{\leftmargin}%
\footnotesize\raggedright%
\begin{lrbox}{\fcolbox}%
\begin{minipage}{\linewidth-4\fboxsep}}%
{\end{minipage}%
\end{lrbox}%
\vspace{3ex}%
\begin{center}%
\fcolorbox{grisfonce}{grisclair}{\usebox{\fcolbox}}%
\end{center}
\vspace{3ex}%
}
\newenvironment{remarque}%
{\begin{greyframe}%
\begin{window}[0,l,{%
\includegraphics[height=0.8cm,keepaspectratio=true]{img/note.png}%
},{}]}%
{\end{window}\end{greyframe}}
\newenvironment{astuce}%
{\begin{greyframe}%
\begin{window}[0,l,{%
\includegraphics[height=0.8cm,keepaspectratio=true]{img/astuce.png}%
},{}]}%
{\end{window}\end{greyframe}}
\newenvironment{rstudio}%
{\begin{greyframe}%
\begin{window}[0,l,{%
\includegraphics[height=0.8cm,keepaspectratio=true]{img/rstudio.png}%
},{}]}%
{\end{window}\end{greyframe}}
\newenvironment{important}%
{\begin{greyframe}%
\begin{window}[0,l,{%
\includegraphics[height=0.8cm,keepaspectratio=true]{img/important.png}%
},{}]}%
{\end{window}\end{greyframe}}
\newenvironment{greyverb}%
{\setlength\fboxsep{10pt}%
\setlength{\rightmargin}{\leftmargin}%
\raggedright%
\begin{lrbox}{\fcolbox}%
\begin{minipage}{\linewidth-4\fboxsep}}%
{\end{minipage}%
\end{lrbox}%
\vspace{3ex}%
\begin{center}%
\fcolorbox{grisinterm}{grisinterm}{\usebox{\fcolbox}}%
\end{center}
\vspace{3ex}%
}
%%%% EXERCICES
\newcounter{ex}
\renewcommand\theex{\thechapter.\arabic{ex}}
\newenvironment{exo}[1]{%
\begin{flushleft}%
\refstepcounter{ex}%
\noindent\textbf{\textsf{Exercice~\theex{}}}\\[0.5ex]%
$\triangleright$ \textit{Solution page \pageref{sol_#1}\\[1ex] }%
\label{exo_#1}}%
{\end{flushleft}}
\newenvironment{solution}[1]{%
\label{sol_#1}%
\begin{flushleft}%
\noindent\textbf{\textsf{\large{}Exercice~\ref{exo_#1}, page \pageref{exo_#1}}}\\[0.5ex]}%
{\end{flushleft}}
\setpapersize[portrait]{A4}
%\setmarginsrb{left}{top}{right}{bottom}{headheight}{headsep}{footheight}{footsep}
\setmarginsrb{2.5cm}{1.5cm}{2.5cm}{2cm}{1cm}{1cm}{1cm}{1.5cm}
\setlength\marginparwidth{40pt}
%\setcounter{tocdepth}{2}
\title{\Huge{Introduction à \includegraphics[width=1.4cm]{img/Rlogo.jpg}}}
\author{Julien Barnier\\ Centre Max Weber\\
\href{mailto:julien.barnier@ens-lyon.fr}{\texttt{julien.barnier@ens-lyon.fr}}}
\date{Version 2.2\\\today{}\\\vspace{3cm}\includegraphics[width=9cm]{img/xkcd_tech_chart.png}\\\footnotesize\texttt{http://xkcd.com/627/}}
\begin{document}
<<initialize,echo=FALSE,results="none",cache=FALSE>>=
options(width=75)
options(max.print="70")
options(prompt="R> ")
opts_chunk$set(fig.path="tmp/",
dev="pdf",
cache=TRUE,
cache.path="cache/",
prompt=TRUE,
tidy=TRUE,
highlight=TRUE,
#size="footnotesize",
comment=NA,
background="0.95;0.95;0.95",
fig.align="center",
out.width=".8\\textwidth")
@
\renewcommand{\chaptername}{Partie}
\renewcommand{\indexname}{Index des fonctions}
\renewcommand{\topfraction}{0.8}
\renewcommand{\bottomfraction}{0.8}
\maketitle
\thispagestyle{empty}
\pagestyle{fancy}
\renewcommand{\chaptermark}[1]{\markboth{#1}{}}
\renewcommand{\sectionmark}[1]{\markright{\thesection.\ #1}}
\fancyhead{}
\fancyhead[RO,LE]{\thepage}
\fancyhead[RE]{\textit{\nouppercase{\leftmark}}}
\fancyhead[LO]{\textit{\nouppercase{\rightmark}}}
\fancyfoot{}
\tableofcontents
\sloppy
\setlength{\parskip}{1ex plus0.1ex minus0.1ex}
\chapter{Introduction}
\section{À propos de ce document}
Ce document a pour objet de fournir une introduction à l'utilisation
du logiciel libre de traitement de données et d'analyse statistiques \R.
Il se veut le plus accessible possible, y compris pour ceux qui ne
sont pas particulièrement familiers avec l'informatique.
Ce document est basé sur \Sexpr{R.Version()[["version.string"]]}.
La page Web <<~officielle~>> sur laquelle on pourra trouver la
dernière version de ce document se trouve à l'adresse~:
\url{http://alea.fr.eu.org/pages/intro-R}
\section{Licence}
\begin{window}[0,r,{%
\includegraphics[width=2.5cm]{img/by-nc-sa_eu.eps}%
},{}]
%\noindent
Ce document est diffusé sous licence \textit{Creative Commons
Attribution - Pas d’utilisation commerciale - Partage dans les mêmes conditions}~:
\end{window}
%\noindent
\url{https://creativecommons.org/licenses/by-nc-sa/3.0/fr/}
\section{Remerciements}
L'auteur tient à remercier Mayeul Kauffmann, Julien Biaudet, Frédérique
Giraud, Joël Gombin pour leurs corrections et suggestions. Et un remerciement
plus particulier à Milan Bouchet-Valat pour sa relecture très attentive et ses
nombreuses et judicieuses remarques.
Joseph Larmarange\footnote{\url{http://joseph.larmarange.net/}} est l'auteur
de l'ensemble des encadrés concernant \textsf{RStudio} et de nombreuses autres
corrections et améliorations. Il maintient par ailleurs une autre version de
ce document, enrichie de chapitres sur différentes méthodes statistiques~:
\url{https://github.com/larmarange/intro-r/tree/CoursM2}
\section{Conventions typographiques}
Ce document suit un certain nombre de conventions typographiques
visant à en faciliter la lecture. Ainsi les noms de logiciel et
d'extensions sont indiqués en caractères sans empattement (\textsf{R},
\textsf{SAS}, \textsf{Linux}, \textsf{questionr}, \textsf{ade4}\ldots). Les
noms de fichiers sont imprimés avec une police à chasse fixe
(\texttt{test.R}, \texttt{data.txt}\ldots), tout comme les fonctions
\R (\rfunc{summary}, \rfunc{mean}, \rfunc{<-}\ldots).
Lorsqu'on présente des commandes saisies sous \R et leur résultat, la commande
saisie est indiquée avec une police à chasse fixe et précédée de l'invite de
commande \texttt{R>}~:
<<eval=FALSE>>=
summary(rnorm(100))
@
Le résultat de la commande tel qu'affiché par \R est également indiqué dans
une police à chasse fixe~:
<<echo=FALSE>>=
summary(rnorm(100))
@
Lorsque la commande \R est trop longue et répartie sur plusieurs
lignes, les lignes suivantes sont précédées du symbole \texttt{+}~:
<<eval=FALSE>>=
coo <- scatterutil.base(dfxy = dfxy, xax = xax, yax = yax, xlim = xlim, ylim = ylim, grid = grid, addaxes = addaxes, cgrid = cgrid, include.origin = include.origin)
@
\section{Présentation de \R}
\R est un langage orienté vers le traitement de données et l'analyse
statistique dérivé du langage \textsf{S}. Il est développé depuis une
vingtaine d'années par un groupe de volontaires de différents pays. C'est un
logiciel libre\footnotemark, publié sous licence GNU GPL.
\footnotetext{Pour plus d'informations sur ce qu'est un logiciel libre,
voir~: \url{http://www.gnu.org/philosophy/free-sw.fr.html}}
L'utilisation de \R présente plusieurs avantages~:
\begin{itemize}
\item c'est un logiciel \textit{multiplateforme}, qui fonctionne aussi bien sur
des sytèmes \textsf{Linux}, \textsf{Mac OS X} ou \textsf{Windows}~;
\item c'est un logiciel \textit{libre}, développé par ses utilisateurs et
modifiable par tout un chacun~;
\item c'est un logiciel \textit{gratuit}~;
\item c'est un logiciel très puissant, dont les fonctionnalités de
base peuvent être étendues à l'aide d'extensions\footnotemark~;
\item c'est un logiciel dont le développement est très actif et dont
la communauté d'utilisateurs ne cesse de s'élargir~;
\item c'est un logiciel avec d'excellentes capacités graphiques.
\end{itemize}
\footnotetext{Il en existe actuellement plus de 8000, disponibles sur le
\textit{Comprehensive R Archive Network} (CRAN)~: \url{http://cran.r-project.org/}}
Comme rien n'est parfait, on peut également trouver quelques inconvénients~:
\begin{itemize}
\item le logiciel, la documentation de référence et les principales
ressources sont en anglais. Il est toutefois parfaitement possible
d'utiliser \R sans spécialement maîtriser cette langue~;
\item il n'existe pas encore d'interface graphique pour \R équivalente à celle
d'autres logiciels comme \textsf{SPSS} ou \textsf{Modalisa}\footnotemark. \R
fonctionne à l'aide de scripts (des petits programmes) édités et exécutés au
fur et à mesure de l'analyse, et se rapprocherait davantage de \textsf{SAS}
dans son utilisation (mais avec une syntaxe et une philosophie très
différentes). Ce point, qui peut apparaître comme un gros handicap, s'avère
après un temps d'apprentissage être un mode d'utilisation d'une grande
souplesse.
\item comme \R s'apparente davantage à un langage de programmation qu'à un
logiciel proprement dite, la courbe d'apprentissage peut être un peu
<<~raide~>>, notamment pour ceux n'ayant jamais programmé auparavant.
\end{itemize}
\footnotetext{Certaines extensions ou logiciels proposent cependant des
interfaces graphiques plus ou moins généralistes. Voir la
section~\ref{sec_guis}, \vpageref{sec_guis} }
\section{Philosophie de \R}
Deux points particuliers dans le fonctionnement de \R peuvent parfois
dérouter les utilisateurs habitués à d'autres logiciels~:
\begin{itemize}
\item sous \R, en général, on ne voit pas les données sur lesquelles
on travaille~; on ne dispose pas en permanence d'une vue des données
sous forme de tableau, comme sous \textsf{Modalisa} ou
\textsf{SPSS}. Ceci peut être déroutant au début, mais on se
rend vite compte qu'on n'a pas besoin de voir en permanence les
données pour les analyser~;
\item avec les autres logiciels, en général la production d'une
analyse génère un grand nombre de résultats de toutes sortes dans
lesquels l'utilisateur est censé retrouver et isoler ceux qui
l'intéressent. Avec \R, c'est l'inverse~: par défaut l'affichage est
réduit au minimum, et c'est l'utilisateur qui demande à voir des
résultats supplémentaires ou plus détaillés.
\end{itemize}
Inhabituel au début, ce fonctionnement permet en fait assez rapidement
de gagner du temps dans la conduite des analyses.
\chapter{Prise en main}
L'installation du logiciel proprement dite n'est pas décrite ici mais
indiquée dans l'annexe~\ref{sec_install},
page~\pageref{sec_install}. On part donc du principe que vous avez
sous la main un ordinateur avec une installation récente de \R, quel
que soit le système d'exploitation que vous utilisez (\textsf{Linux},
\textsf{Mac OS X} ou \textsf{Windows}).
\begin{rstudio}
Le projet \textsf{RStudio} tend à s'imposer comme l'environnement de
développement de référence pour \R, d'autant qu'il a l'avantage d'être
libre, gratuit et multiplateforme. Son installation est décrite
section~\ref{sec_rstudio} \vpageref{sec_rstudio}.
Les astuces et informations spécifiques à \textsf{RStudio} seront présentées
tout au long de ce document dans des encadrés similaires à celui-là.
\textsf{RStudio} peut tout à fait être utilisé pour découvrir et démarrer
avec \R.
\end{rstudio}
\section{L'invite de commandes}
Une fois \R lancé, vous obtenez une fenêtre appelée
\textit{console}. Celle-ci contient un petit texte de bienvenue
ressemblant à peu près à ce qui suit\footnotemark~:
\footnotetext{La figure~\ref{fig_RGui} \vpageref{fig_RGui} montre
l'interface par défaut sous \textsf{Windows}.}
\begin{figure}
\begin{center}
\includegraphics[width=0.8\textwidth]{img/scr_RGui.png}
\end{center}
\caption{L'interface de \R sous \textsf{Windows} au démarrage}
\label{fig_RGui}
\end{figure}
\begin{greyverb}
\begin{verbatim}
R version 3.2.4 (2016-03-10) -- "Very Secure Dishes"
Copyright (C) 2016 The R Foundation for Statistical Computing
Platform: x86_64-pc-linux-gnu (64-bit)
R est un logiciel libre livré sans AUCUNE GARANTIE.
Vous pouvez le redistribuer sous certaines conditions.
Tapez 'license()' ou 'licence()' pour plus de détails.
(...)
\end{verbatim}
\end{greyverb}
\noindent
suivi d'une ligne commençant par le caractère \texttt{>} et sur laquelle
devrait se trouver votre curseur. Cette ligne est appelée
l'\textit{invite de commande} (ou \textit{prompt} en anglais). Elle
signifie que \R est disponible et en attente de votre prochaine
commande.
\begin{figure}
\begin{center}
\includegraphics[width=0.8\textwidth]{img/scr_RStudio.png}
\end{center}
\caption{L'interface de \textsf{RStudio} au démarrage}
\label{fig_RStudio}
\end{figure}
\begin{rstudio}
L'interface de \textsf{RStudio} se présente différement (voir
figure~\ref{fig_RStudio}). Elle est divisée en quatre parties. Le quadrant
haut-gauche est dédié aux fichiers sources (scripts). Le quadrant haut-droite
fournit des informations sur vos données en mémoire et votre historique. Le
quadrant bas-droite vous permet naviguer dans votre répertoire de travail,
affiche l'aide, vos graphiques et les extensions disponibles. Enfin, la
\textit{console} est affichée en bas à gauche. C'est elle qui nous intéresse
pour le moment. Nous aborderons les autres quadrants plus loin dans ce
document.
\end{rstudio}
Nous allons tout de suite lui fournir une première commande~:
<<>>=
2 + 3
@
Bien, nous savons désormais que \R sait faire les additions à un
chiffre\footnotemark. Nous pouvons désormais continuer avec d'autres
opérations arithmétiques de base~:
\footnotetext{La présence du \texttt{[1]} en début de ligne sera
expliquée par la suite, \vpageref{explication_crochets}.}
<<>>=
8 - 12
14 * 25
-3 / 10
@
\begin{astuce}
Une petite astuce très utile lorsque vous tapez des commandes
directement dans la console~: en utilisant les flèches \textit{Haut}
et \textit{Bas} du clavier, vous pouvez naviguer dans l'historique
des commandes tapées précédemment, que vous pouvez alors facilement
réexécuter ou modifier.
\end{astuce}
\begin{rstudio}
Sous \textsf{RStudio}, l'onglet \textit{History} du quadrant haut-droite vous
permet de consulter l'historique des commandes que vous avez transmises à \R.
Un double-clic sur une commande la recopiera automatiquement dans la console.
Vous pouvez également sélectionner une ou plusieurs commandes puis cliquer sur
\textit{To Console}. Voir également (en anglais) : \url{http://www.rstudio.com/ide/docs/using/history}
\end{rstudio}
Lorsqu'on fournit à \R une commande incomplète, celui-ci nous propose
de la compléter en nous présentant une invite de commande spéciale
utilisant les signe \texttt{+}. Imaginons par exemple que nous avons
malencontreusement tapé sur \texttt{Entrée} alors que nous souhaitions
calculer \texttt{4*3}:
\begin{greyverb}
\begin{verbatim}
4 *
\end{verbatim}
\end{greyverb}
On peut alors compléter la commande en saisissant simplement
\texttt{3}~:
<<incomp2,eval=TRUE,prompt=TRUE,tidy=FALSE>>=
4 *
3
@
\begin{astuce}
Pour des commandes plus complexes, il arrive parfois qu'on se
retrouve coincé avec un invite \texttt{+} sans plus savoir comment
compléter la saisie correctement. On peut alors annuler la commande
en utilisant la touche \texttt{Echap} ou \texttt{Esc} sous
\textsf{Windows}. Sous \textsf{Linux} on utilise le traditionnel
\texttt{Control + C}.
\end{astuce}
À noter que les espaces autour des opérateurs n'ont pas d'importance
lorsque l'on saisit les commandes dans \R. Les trois commandes
suivantes sont donc équivalentes, mais on privilégie en général la
deuxième pour des raisons de lisibilité du code.
<<espaces,eval=FALSE,prompt=TRUE,tidy=FALSE>>=
10+2
10 + 2
10 + 2
@
\section{Des objets}
\subsection{Objets simples}
Faire des opérations arithmétiques, c'est bien, mais sans doute pas
totalement suffisant. Notamment, on aimerait pouvoir réutiliser le
résultat d'une opération sans avoir à le resaisir ou à le
copier/coller.
Comme tout langage de programmation, \R permet de faire cela en
utilisant des \textit{objets}. Prenons tout de suite un exemple~:
<<>>=
x <- 2
@
Que signifie cette commande~? L'opérateur \rfunc{<-} est appelé
\textit{opérateur d'assignation}. Il prend une valeur quelconque à
droite et la place dans l'objet indiqué à gauche. La commande pourrait
donc se lire \textit{mettre la valeur 2 dans l'objet nommé} \texttt{x}.
On va ensuite pouvoir réutiliser cet objet dans d'autres calculs ou
simplement afficher son contenu~:
<<>>=
x + 3
x
@
\begin{remarque}
Par défaut, si on donne à \R seulement le nom d'un objet, il va se
débrouiller pour nous présenter son contenu d'une manière plus ou
moins lisible.
\end{remarque}
On peut utiliser autant d'objets qu'on veut. Ceux-ci peuvent contenir
des nombres, des chaînes de caractères (indiquées par des guillemets
droits \texttt{"}) et bien d'autres choses encore~:
<<>>=
x <- 27
y <- 10
foo <- x + y
foo
x <- "Hello"
foo <- x
foo
@
\begin{remarque}
\label{rq_noms}
Les noms d'objets peuvent contenir des lettres, des chiffres (mais
ils ne peuvent pas commencer par un chiffre), les symboles
\texttt{.} et \texttt{\_}, et doivent commencer par une lettre. \R
fait la différence entre les majuscules et les minuscules, ce qui
signifie que \texttt{x} et \texttt{X} sont deux objets
différents. On évitera également d'utiliser des caractères accentués
dans les noms d'objets, et comme les espaces ne sont pas autorisés
on pourra les remplacer par un point ou un tiret bas.
Enfin, signalons que certains noms courts sont réservés par \R pour
son usage interne et doivent être évités. On citera notamment
\texttt{c, q, t, C, D, F, I, T, max, min}\ldots
\end{remarque}
\subsection{Vecteurs}
Imaginons maintenant que nous avons interrogé dix personnes au hasard
dans la rue et que nous avons relevé pour chacune d'elle sa taille en
centimètres. Nous avons donc une série de dix nombres que nous
souhaiterions pouvoir réunir de manière à pouvoir travailler sur
l'ensemble de nos mesures.
Un ensemble de données de même nature constituent pour \R un
\textit{vecteur} (en anglais \textit{vector}) et se construit à l'aide
d'un opérateur nommé \rfunc{c}\footnotemark. On l'utilise en lui
donnant la liste de nos données, entre parenthèses, séparées par des
virgules~:
\footnotetext{\rfunc{c} est l'abbréviation de \textit{combine}. Le
nom de cette fonction est très court car on l'utilise très souvent.}
<<>>=
tailles <- c(167, 192, 173, 174, 172, 167, 171, 185, 163, 170)
@
Ce faisant, nous avons créé un objet nommé \texttt{tailles} et
comprenant l'ensemble de nos données, que nous pouvons afficher~:
<<>>=
tailles
@
Dans le cas où notre vecteur serait beaucoup plus grand, et
comporterait par exemple 40 tailles, on aurait le résultat suivant~:
<<echo=FALSE>>=
tailles <- c(144, 168, 179, 175, 182, 188, 167, 152, 163, 145, 176, 155,
156, 164, 167, 155, 157, 185, 155, 169, 124, 178, 182, 195, 151,
185, 159, 156, 184, 172, 156, 160, 183, 148, 182, 126, 177, 159,
143, 161, 180, 169, 159, 185, 160)
@
<<>>=
tailles
@
\label{explication_crochets}
On a bien notre suite de quarante tailles, mais on peut remarquer la
présence de nombres entre crochets au début de chaque ligne
(\texttt{[1]}, \texttt{[18]} et \texttt{[35]}). En fait ces nombres
entre crochets indiquent la position du premier élément de la ligne
dans notre vecteur. Ainsi, le 185 en début de deuxième ligne est le
18\up{e} élément du vecteur, tandis que le 182 de la troisième ligne est
à la 35\up{e} position.
On en déduira d'ailleurs que lorsque l'on fait~:
<<>>=
2
@
\R considère en fait le nombre 2 comme un vecteur à un seul élément.
On peut appliquer des opérations arithmétiques simples directement sur
des vecteurs~:
<<>>=
tailles <- c(167, 192, 173, 174, 172, 167, 171, 185, 163, 170)
tailles + 20
tailles / 100
tailles ^ 2
@
On peut aussi combiner des vecteurs entre eux. L'exemple suivant
calcule l'indice de masse corporelle à partir de la taille et du
poids~:
<<>>=
tailles <- c(167, 192, 173, 174, 172, 167, 171, 185, 163, 170)
poids <- c(86, 74, 83, 50, 78, 66, 66, 51, 50, 55)
tailles.m <- tailles / 100
imc <- poids / (tailles.m ^ 2)
imc
@
\begin{remarque}
Quand on fait des opérations sur les vecteurs, il faut veiller à
soit utiliser un vecteur et un chiffre (dans des opérations du type
\texttt{v * 2} ou \texttt{v + 10}), soit à utiliser des vecteurs de
même longueur (dans des opérations du type \texttt{u + v}).
Si on utilise des vecteurs de longueur différentes, on peut avoir
quelques surprises\footnotemark.
\end{remarque}
\footnotetext{Quand \R effectue une opération avec deux vecteurs de
longueurs différentes, il recopie le vecteur le plus court de
manière à lui donner la même taille que le plus long, ce qui
s'appelle la \textit{règle de recyclage} (\textit{recycling
rule}). Ainsi, \texttt{c(1,2) + c(4,5,6,7,8)} vaudra l'équivalent
de \texttt{c(1,2,1,2,1) + c(4,5,6,7,8)}.}
On a vu jusque-là des vecteurs composés de nombres, mais on peut tout
à fait créer des vecteurs composés de chaînes de caractères,
représentant par exemple les réponses à une question ouverte ou fermée~:
<<>>=
reponse <- c("Bac+2", "Bac", "CAP", "Bac", "Bac", "CAP", "BEP")
@
Enfin, notons que l'on peut accéder à un élément particulier du
vecteur en faisant suivre le nom du vecteur de crochets contenant le
numéro de l'élément désiré. Par exemple~:
<<>>=
reponse <- c("Bac+2", "Bac", "CAP", "Bac", "Bac", "CAP", "BEP")
reponse[2]
@
Cette opération s'appelle \textit{l'indexation} d'un vecteur. Il
s'agit ici de sa forme la plus simple, mais il en existe d'autres
beaucoup plus complexes. L'indexation des vecteurs et des tableaux
dans \R est l'un des éléments particulièrement souples et puissants du
langage (mais aussi l'un des plus délicats à comprendre et à
maîtriser). Nous en reparlerons section~\ref{sec_indexation}
\vpageref{sec_indexation}.
\begin{rstudio}
Sous \textsf{RStudio}, vous avez dû remarquer que ce dernier effectue une
coloration syntaxique. Lorsque vous tapez une commande, les valeurs numériques
sont affichées dans une certaine couleur, les valeurs textuelles dans une
autre et les noms des fonctions dans une troisième. De plus, si vous tapez une
parenthèse ouvrante, \textsf{RStudio} va créer automatiquement après le
curseur la parenthèse fermante correspondante (de même avec les guillements).
De plus, si vous placez le curseur juste après une parenthèse fermante, la
parenthèse ouvrante correspondante sera surlignée, ce qui sera bien pratique
lors de la rédaction de commandes complexes.
\end{rstudio}
\section{Des fonctions}
Nous savons désormais faire des opérations simples sur des nombres et
des vecteurs, stocker ces données et résultats dans des objets pour
les réutiliser par la suite.
Pour aller un peu plus loin nous allons aborder, après les
\textit{objets}, l'autre concept de base de \R, à savoir les
\textit{fonctions}. Une fonction se caractérise de la manière
suivante~:
\begin{itemize}
\item elle a un nom~;
\item elle accepte des arguments (qui peuvent avoir un nom ou pas)~;
\item elle retourne un résultat et peut effectuer une action comme
dessiner un graphique, lire un fichier, etc.~;
\end{itemize}
En fait rien de bien nouveau puisque nous avons déjà utilisé plusieurs
fonctions jusqu'ici, dont la plus visible est la fonction
\rfunc{c}. Dans la ligne suivante~:
<<>>=
reponse <- c("Bac+2", "Bac", "CAP", "Bac", "Bac", "CAP", "BEP")
@
\noindent
on fait appel à la fonction nommée \rfunc{c}, on lui passe en
arguments (entre parenthèses et séparées par des virgules) une série
de chaînes de caractères, et elle retourne comme résultat un vecteur
de chaînes de caractères, que nous stockons dans l'objet
\texttt{reponse}.
Prenons tout de suite d'autres exemples de fonctions courantes~:
<<>>=
tailles <- c(167, 192, 173, 174, 172, 167, 171, 185, 163, 170)
length(tailles)
mean(tailles)
var(tailles)
@
Ici, la fonction \rfunc{length} nous renvoie le nombre d'éléments du
vecteur, la fonction \rfunc{mean} nous donne la moyenne des éléments
du vecteur et la fonction \rfunc{var} sa variance.
\subsection{Arguments}
Les arguments de la fonction lui sont indiqués entre parenthèses,
juste après son nom. En général les premiers arguments passés à la
fonction sont des données servant au calcul, et les suivants des
paramètres influant sur ce calcul. Ceux-ci sont en général transmis
sous la forme d'argument nommés.
Reprenons l'exemple des tailles précédent~:
<<>>=
tailles <- c(167, 192, 173, 174, 172, 167, 171, 185, 163, 170)
@
Imaginons que le deuxième enquêté n'ait pas voulu nous répondre. Nous
avons alors dans notre vecteur une valeur manquante. Celle-ci est
symbolisée dans \R par le code \texttt{NA}~:
<<>>=
tailles <- c(167, NA, 173, 174, 172, 167, 171, 185, 163, 170)
@
Recalculons notre taille moyenne~:
<<>>=
mean(tailles)
@
Et oui, par défaut, \R renvoie \texttt{NA} pour un grand nombre de
calculs (dont la moyenne) lorsque les données comportent une valeur
manquante. On peut cependant modifier ce comportement en fournissant
un paramètre supplémentaire à la fonction \rfunc{mean}, nommé \texttt{na.rm}~:
<<>>=
mean(tailles, na.rm=TRUE)
@
Positionner le paramètre \texttt{na.rm} à \texttt{TRUE} (vrai) indique
à la fonction \rfunc{mean} de ne pas tenir compte des valeurs
manquantes dans le calcul.
Lorsqu'on passe un argument à une fonction de cette manière,
c'est-à-dire sous la forme \texttt{nom=valeur}, on parle
d'\textit{argument nommé}.
\begin{important}
\texttt{NA} signifie \textit{not available}. Cette valeur particulière peut
être utilisée pour indiquer une valeur manquante pour tout type de liste
(nombres, textes, valeurs logique, etc.).
\end{important}
\subsection{Quelques fonctions utiles}
Récapitulons la liste des fonctions que nous avons déjà rencontrées~:
\begin{center}
\begin{tabular}{rl}
\textbf{Fonction} & \textbf{Description} \\
\hline
\rfunc{c} & construit un vecteur à partir d'une série de valeurs \\
\rfunc{length} & nombre d'éléments d'un vecteur \\
\rfunc{mean} & moyenne d'un vecteur de type numérique \\
\rfunc{var} & variance d'un vecteur de type numérique \\
\rfunc{+}, \rfunc{-}, \rfunc{*}, \rfunc{/} & opérateurs mathématiques de base \\
\texttt{\^}\index{^@\texttt{\^}} & passage à la puissance \\
\end{tabular}
\end{center}
On peut rajouter les fonctions de base suivantes~:
\begin{center}
\begin{tabular}{rl}
\textbf{Fonction} & \textbf{Description} \\
\hline
\rfunc{min} & valeur minimale d'un vecteur numérique \\
\rfunc{max} & valeur maximale d'un vecteur numérique \\
\rfunc{sd} & écart-type d'un vecteur numérique \\
\rfunc{:} & génère une séquence de nombres. \verb|1:4| équivaut à \texttt{c(1,2,3,4)} \\
\end{tabular}
\end{center}
\begin{rstudio}
Autre outil bien utile de \textsf{RStudio}, l'auto-complétion. Tapez les
premières lettres d'une fonction, par exemple \texttt{me} puis appuyez sur la
touche \texttt{<Tabulation>}. \textsf{RStudio} affichera la liste des fonctions
dont le nom commence par \texttt{me} ainsi qu'un court descriptif de chacune.
Un appui sur la touche \textit{Entrée} provoquera la saisie du nom complet de
la fonction choisie. Vous pouvez également utiliser l'auto-complétion pour
retrouver un objet que vous avez créé --- par exemple, appuyez sur la touche
\texttt{<Tabulation>} après avoir saisi \texttt{mean(t} --- ou bien pour retrouver
un argument nommé d'une fonction --- par exemple, appuyez sur la touche
\texttt{<Tabulation>} après avoir saisi \texttt{mean(taille,}.
\end{rstudio}
\subsection{Aide sur une fonction}
Il est très fréquent de ne plus se rappeler quels sont les paramètres
d'une fonction ou le type de résultat qu'elle retourne. Dans ce cas on
peut très facilement accéder à l'aide décrivant une fonction
particulière en tapant (remplacer \texttt{fonction} par le nom de la
fonction)~:
<<eval=FALSE>>=
help("fonction")
@
Ou, de manière équivalente, \texttt{?fonction}\footnote{L'utilisation
du raccourci \texttt{?fonction} ne fonctionne pas pour certains
opérateurs comme \texttt{*}. Dans ce cas on pourra utiliser
\texttt{?'*'} ou bien simplement \texttt{help("*")}.}.
Ces deux commandes affichent une page (en anglais) décrivant la
fonction, ses paramètres, son résultat, le tout accompagné de diverses
notes, références et exemples. Ces pages d'aide contiennent à peu près
tout ce que vous pourrez chercher à savoir, mais elles ne sont pas
toujours d'une lecture aisée.
Un autre cas très courant dans \R est de ne pas se souvenir ou de ne
pas connaître le nom de la fonction effectuant une tâche donnée. Dans
ce cas on se reportera aux différentes manières de trouver de l'aide
décrites dans l'annexe~\ref{sec_aide}, page~\pageref{sec_aide}.
\begin{rstudio}
Dans \textsf{RStudio}, les pages d'aide en ligne s'ouvriront dans le quadrant
bas-droite sous l'onglet \textit{Help}. Un clic sur l'icône en forme de maison
vous affichera la page d'accueil de l'aide.
\end{rstudio}
\section{Exercices}
\begin{exo}{simplec}
Construire le vecteur suivant~:
<<echo=FALSE>>=
c(120, 134, 256, 12)
@
\end{exo}
\begin{exo}{simplec2}
Construire le vecteur suivant~:
<<echo=FALSE>>=
1:9
@
À partir de ce premier vecteur, générer les deux vecteurs suivants :
<<echo=FALSE>>=
1:9 + 100
1:9 * 2
@
\end{exo}
\begin{exo}{sommevect}
On a demandé à 4 ménages le revenu des deux conjoints, et le nombre de
personnes du ménage~:
<<eval=FALSE>>=
conjoint1 <- c(1200, 1180, 1750, 2100)
conjoint2 <- c(1450, 1870, 1690, 0)
nb.personnes <- c(4, 2, 3, 2)
@
Calculez le revenu total par personne du ménage.
\end{exo}
\begin{exo}{maxvect}
Dans l'exercice précédent, calculez le revenu minimum et le revenu
maximum parmi ceux du premier conjoint~:
<<eval=FALSE>>=
conjoint1 <- c(1200, 1180, 1750, 2100)
@
Recommencer avec les revenus suivants, parmi lesquels l'un des
enquêtés n'a pas voulu répondre~:
<<eval=FALSE>>=
conjoint1.na <- c(1200, 1180, 1750, NA)
@
\end{exo}
\chapter{Premier travail avec des données}
\section{Regrouper les commandes dans des scripts}
Jusqu'à maintenant nous avons utilisé uniquement la console pour
communiquer avec \R \textit{via} l'invite de commandes. Le principal
problème de ce mode d'interaction est qu'une fois qu'une commande est
tapée, elle est pour ainsi dire <<~perdue~>>, c'est-à-dire qu'on doit
la saisir à nouveau si on veut l'exécuter une seconde
fois. L'utilisation de la console est donc restreinte aux petites
commandes <<~jetables~>>, le plus souvent utilisées comme test.
La plupart du temps, les commandes seront stockées dans un fichier à
part, que l'on pourra facilement ouvrir, éditer et exécuter en tout ou
partie si besoin. On appelle en général ce type de fichier un
\textit{script}.
Pour comprendre comment cela fonctionne, dans le menu
\textit{Fichier}, sélectionnez l'entrée \textit{Nouveau script}\footnotemark. Une
nouvelle fenêtre (vide) apparaît. Nous pouvons désormais y
saisir des commandes. Par exemple, tapez sur la première ligne la
commande suivante~:
\begin{greyverb}
\begin{verbatim}
2+2
\end{verbatim}
\end{greyverb}
\footnotetext{Les indications données ici concernent l'interface par
défaut de \R sous \textsf{Windows}. Elles sont très semblables sous
\textsf{Mac OS X}.}
Ensuite, allez dans le menu \textit{Éditon}, et choisissez
\textit{Exécuter la ligne ou sélection}. Apparement rien ne se passe,
mais si vous jetez un \oe{}il à la fenêtre de la console, les lignes
suivantes ont dû faire leur apparition~:
<<exec,tidy=FALSE>>=
2+2
@
Voici donc comment soumettre rapidement à \R les commandes saisies dans
votre fichier. Vous pouvez désormais l'enregistrer, l'ouvrir plus
tard, et en exécuter tout ou partie. À noter que vous avez plusieurs
possibilités pour soumettre des commandes à \R~:
\begin{itemize}
\item vous pouvez exécuter la ligne sur laquelle se trouve votre
curseur en sélectionnant \textit{Éditon} puis \textit{Exécuter la
ligne ou sélection}, ou plus simplement en appuyant simultanément
sur les touches \texttt{<Ctrl>} et \texttt{<R>}\footnote{Sous
\textsf{Mac OS X}, on utilise les touches \texttt{<Pomme>} et
\texttt{<Entrée>}.}~;
\item vous pouvez sélectionner plusieurs lignes contenant des
commandes et les exécuter toutes en une seule fois exactement de la
même manière~;
\item vous pouvez exécuter d'un coup l'intégralité de votre fichier en
choisissant \textit{Édition} puis \textit{Exécuter tout}.
\end{itemize}
La plupart du travail sous \R consistera donc à éditer un ou plusieurs
fichiers de commandes et à envoyer régulièrement les commandes saisies
à \R en utilisant les raccourcis clavier \textit{ad hoc}.
\begin{rstudio}
Les commandes sont légèrement différentes avec \textsf{RStudio} mais le
principe est le même. Pour créer un nouveau script \R, faire \textit{File >
New file > R Script}. Votre nouveau fichier apparaitra dans le quadrant haut-gauche.
Pour exécuter une ou plusieurs lignes de code, sélectionnez les lignes en
question puis cliquez sur l'icône \textit{Run} ou bien appuyez simultanément
sur les touches \texttt{<Ctrl>} et \texttt{<Entrée>}.
Pour plus d'astuces (en anglais) : \url{http://www.rstudio.com/ide/docs/using/source}
\end{rstudio}
\section{Ajouter des commentaires}
Un commentaire est une ligne ou une portion de ligne qui sera ignorée
par \R. Ceci signifie qu'on peut y écrire ce qu'on veut, et qu'on va
les utiliser pour ajouter tout un tas de commentaires à notre code
permettant de décrire les différentes étapes du travail, les choses à
se rappeler, les questions en suspens, etc.
Un commentaire sous \R commence par un ou plusieurs symboles
\texttt{\#} (qui s'obtient avec les touches \texttt{<Alt~Gr>} et
\texttt{<3>} sur les claviers de type PC). Tout ce qui suit ce symbole
jusqu'à la fin de la ligne est considéré comme un commentaire. On peut
créer une ligne entière de commentaire, par exemple en la faisant
débuter par \texttt{\#\#}~:
<<commentaire1,prompt=FALSE,eval=FALSE,tidy=FALSE>>=
## Tableau croisé de la CSP par le nombre de livres lus
## Attention au nombre de non réponses !
@
On peut aussi créer des commentaires pour une ligne en cours~:
<<commentaire2,prompt=FALSE,eval=FALSE,tidy=FALSE>>=
x <- 2 # On met 2 dans x, parce qu'il le vaut bien
@
\begin{important}
Dans tous les cas, il est très important de documenter ses fichiers \R
au fur et à mesure, faute de quoi on risque de ne plus y comprendre
grand chose si on les reprend ne serait-ce que quelques semaines plus
tard.
\end{important}
\begin{rstudio}
Avec \textsf{RStudio}, vous pouvez également utiliser les commentaires pour
créer des sections au sein de votre script et naviguer plus rapidement.
Voir (en anglais) : \url{http://www.rstudio.com/ide/docs/using/code_folding}
\end{rstudio}
\section{Tableaux de données}
Dans cette partie nous allons utiliser un jeu de données inclus dans
l'extension \questionr.\marqr{} Cette extension et son
installation sont décrites dans la partie~\ref{sec_questionr},
page~\pageref{sec_questionr}.
Le jeu de données en question est un extrait de l'enquête
\textit{Histoire de vie} réalisée par l'INSEE en 2003. Il contient
2000 individus et 20 variables. Le descriptif des variables est
indiqué dans l'annexe~\ref{sec_hdv2003}, page~\pageref{sec_hdv2003}.
Pour pouvoir utiliser ces données, il faut d'abord charger l'extension
\questionr (après l'avoir installée, bien entendu)~:
<<>>=
library(questionr)
@
Puis indiquer à \R que nous souhaitons accéder au jeu de données à
l'aide de la commande \rfunc{data}~:
<<>>=
data(hdv2003)
@
Bien. Et maintenant, elles sont où mes données ? Et bien elles se
trouvent dans un objet nommé \texttt{hdv2003} désormais accessible
directement. Essayons de taper son nom à l'invite de commande~:
<<eval=FALSE>>=
hdv2003
@
Le résultat (non reproduit ici) ne ressemble pas forcément à
grand-chose\ldots Il faut se rappeler que par défaut, lorsqu'on lui
fournit seulement un nom d'objet, \R essaye de l'afficher de la
manière la meilleure (ou la moins pire) possible. La réponse à la
commande \texttt{hdv2003} n'est donc rien moins que l'affichage des
données brutes contenues dans cet objet.
Ce qui signifie donc que l'intégralité de notre jeu de données est
inclus dans l'objet nommé \texttt{hdv2003}~! En effet, dans \R, un
objet peut très bien contenir un simple nombre, un vecteur ou bien le
résultat d'une enquête tout entier. Dans ce cas, les objets sont
appelés des \textit{data frames}, ou tableaux de données. Ils peuvent
être manipulés comme tout autre objet. Par exemple~:
<<>>=
d <- hdv2003
@
va entraîner la copie de l'ensemble de nos données dans un nouvel
objet nommé \texttt{d}, ce qui peut paraître parfaitement inutile mais
a en fait l'avantage de fournir un objet avec un nom beaucoup plus
court, ce qui diminuera la quantité de texte à saisir par la suite.
\paragraph{Résumons} Comme nous avons désormais décidé de saisir nos
commandes dans un script et non plus directement dans la console, les
premières lignes de notre fichier de travail sur les données de
l'enquête \textit{Histoire de vie} pourraient donc ressembler à ceci~:
<<resumtab,prompt=FALSE,eval=FALSE,tidy=FALSE>>=
## Chargement des extensions nécessaires
library(questionr)
## Jeu de données hdv2003
data(hdv2003)
d <- hdv2003
@
\section{Inspecter les données}
\subsection{Structure du tableau}
Avant de travailler sur les données, nous allons essayer de voir à
quoi elles ressemblent. Dans notre cas il s'agit de se familiariser
avec la stucture du fichier. Lors de l'import de données depuis un
autre logiciel, il s'agira souvent de vérifier que l'importation s'est
bien déroulée.
Les fonctions \rfunc{nrow}, \rfunc{ncol} et \rfunc{dim} donnent
respectivement le nombre de lignes, le nombre de colonnes et les
dimensions de notre tableau. Nous pouvons donc d'ores et déjà vérifier
que nous avons bien 2000 lignes et 20 colonnes~:
<<>>=
nrow(d)
ncol(d)
dim(d)
@
La fonction \rfunc{names} donne les noms des colonnes de notre
tableau, c'est-à-dire les noms des variables~:
<<>>=
names(d)
@
La fonction \rfunc{str} est plus complète. Elle liste les différentes
variables, indique leur type et donne le cas échéant des informations
supplémentaires ainsi qu'un échantillon des premières valeurs prises
par cette variable~:
<<>>=
str(d)
@
La première ligne nous informe qu'il s'agit bien d'un tableau de
données avec 2000 observations et 20 variables. Vient ensuite la liste
des variables. La première se nomme \texttt{id} et est de type
\textit{nombre entier} (\texttt{int}). La seconde se nomme
\texttt{age} et est de type \textit{numérique}. La troisième se nomme
\texttt{sexe}, il s'agit d'un \textit{facteur} (\textit{factor}).
Un \textit{facteur} et une variable pouvant prendre un nombre limité
de modalités (\textit{levels}). Ici notre variable a deux modalités
possibles~: \texttt{Homme} et \texttt{Femme}. Ce type de variable est
décrit plus en détail section~\ref{sec_factor} \vpageref{sec_factor}.
\begin{astuce}
La fonction \rfunc{str} peut s'appliquer à n'importe quel type d'objet. C'est
un excellent moyen de connaître la structure d'un objet.
\end{astuce}
\subsection{Inspection visuelle}
La particularité de \R par rapport à d'autres logiciels comme
\textsf{Modalisa} ou \textsf{SPSS} est de ne pas proposer, par défaut,
de vue des données sous forme de tableau. Ceci peut parfois être un
peu déstabilisant dans les premiers temps d'utilisation, même si on
perd vite l'habitude et qu'on finit par se rendre compte que
<<~voir~>> les données n'est pas forcément un gage de productivité ou
de rigueur dans le traitement.
Néanmoins, \R propose une visualisation assez rudimentaire des données
sous la forme d'une fenêtre de type tableur, \textit{via} la fonction \rfunc{edit}~:
<<eval=FALSE>>=
edit(d)
@
La fenêtre qui s'affiche permet de naviguer dans le tableau, et même
d'éditer le contenu des cases et donc de modifier les données. Lorsque
vous fermez la fenêtre, le contenu du tableau s'affiche dans la
console~: il s'agit en fait du tableau comportant les éventuelles
modifications effectuées, \texttt{d} restant inchangé. Si vous
souhaitez appliquer ces modifications, vous pouvez le faire en créant
un nouveau tableau~:
<<eval=FALSE>>=
d.modif <- edit(d)
@
ou en remplaçant directement le contenu de \texttt{d}\footnote{Dans ce
cas on peut utiliser la fonction \rfunc{fix} sous la forme
\texttt{fix(d)}, qui est équivalente à \texttt{d <- edit(d)}.}~:
<<eval=FALSE>>=
d <- edit(d)
@
\begin{important}
La fonction \rfunc{edit} peut être utile pour un avoir un aperçu
visuel des données, par contre il est \textbf{très fortement}
déconseillé de l'utiliser pour modifier les données. Si on souhaite
effectuer des modifications, on remonte en général aux données
originales (retouches ponctuelles dans un tableur par exemple) ou on
les effectue à l'aide de commandes (qui seront du coup
reproductibles).
\end{important}
\begin{rstudio}
Sous \textsf{RStudio}, la liste des objets en mémoire est affichée dans le
quadrant haut-droite sous l'onglet \textit{Workspace}. Un clic sur un tableau
de données permet d'afficher son contenu sous un onglet dédié dans le quadrant
haut-gauche. Cette manière de procéder est plus simple que le recours à la
fonction \rfunc{edit}.
\end{rstudio}
\subsection{Accéder aux variables}
\texttt{d} représente donc l'ensemble de notre tableau de
données. Nous avons vu que si l'on saisit simplement \texttt{d} à
l'invite de commandes, on obtient un affichage du tableau en
question. Mais comment accéder aux variables, c'est à dire aux
colonnes de notre tableau~?
La réponse est simple~: on utilise le nom de l'objet, suivi de
l'opérateur \rfunc{\$}, suivi du nom de la variable, comme ceci~:
<<>>=
d$sexe
@
On constate alors que \R a bien accédé au contenu de notre variable
\texttt{sexe} du tableau \texttt{d} et a affiché son contenu,
c'est-à-dire l'ensemble des valeurs prises par la variable.
Les fonctions \rfunc{head} et \rfunc{tail} permettent d'afficher
seulement les premières (respectivement les dernières) valeurs prises
par la variable. On peut leur passer en argument le nombre d'éléments
à afficher~:
<<>>=
head(d$sport)
tail(d$age,10)
@
À noter que ces fonctions marchent aussi pour afficher les lignes du
tableau \texttt{d}~:
<<>>=
head(d,2)
@
\section{Analyser une variable}
\subsection{Variable quantitative}
\subsubsection{Principaux indicateurs}
Comme la fonction \rfunc{str} nous l'a indiqué, notre tableau
\texttt{d} contient plusieurs valeurs numériques, dont la variable
\texttt{heures.tv} qui représente le nombre moyen passé par les
enquêtés à regarder la télévision quotidiennement. On peut essayer de
déterminer quelques caractéristiques de cette variable, en utilisant
des fonctions déjà vues précédemment~:
<<>>=
mean(d$heures.tv)
mean(d$heures.tv, na.rm=TRUE)
sd(d$heures.tv, na.rm=TRUE)
min(d$heures.tv, na.rm=TRUE)
max(d$heures.tv, na.rm=TRUE)
range(d$heures.tv, na.rm=TRUE)
@
On peut lui ajouter la fonction \rfunc{median}, qui donne la valeur
médiane, et le très utile \rfunc{summary} qui donne toutes ces
informations ou presque en une seule fois, avec en plus les valeurs des
premier et troisième quartiles et le nombre de valeurs manquantes (\texttt{NA})~:
<<>>=
median(d$heures.tv,na.rm=TRUE)
summary(d$heures.tv)
@
\begin{astuce}
La fonction \rfunc{summary} peut-être utilisée sur tout type d'objet, y
compris un tableau de données. Essayez donc \texttt{summary(d)}.
\end{astuce}
\subsubsection{Histogramme}
Tout cela est bien pratique, mais pour pouvoir observer la
distribution des valeurs d'une variable quantitative, il n'y a quand
même rien de mieux qu'un bon graphique.
On peut commencer par un histogramme de la répartition des
valeurs. Celui-ci peut être généré très facilement avec la fonction
\rfunc{hist}, comme indiqué figure~\ref{fig_hist1}
\vpageref{fig_hist1}.
\begin{figure}
<<hist1>>=
hist(d$heures.tv, main="Nombre d'heures passées devant la télé par jour", xlab="Heures", ylab="Effectif")
@
\caption{Exemple d'histogramme}
\label{fig_hist1}
\end{figure}
Ici, les options \texttt{main}, \texttt{xlab} et \texttt{ylab}
permettent de personnaliser le titre du graphique, ainsi que les
étiquettes des axes. De nombreuses autres options existent pour
personnaliser l'histogramme, parmi celles-ci on notera~:
\begin{description}
\item[probability] si elle vaut \texttt{TRUE}, l'histogramme indique
la proportion des classes de valeurs au lieu des effectifs.
\item[breaks] permet de contrôler les classes de valeurs. On peut lui
passer un chiffre, qui indiquera alors le nombre de classes, un
vecteur, qui indique alors les limites des différentes classes, ou
encore une chaîne de caractère ou une fonction indiquant comment les
classes doivent être calculées.
\item[col] la couleur de l'histogramme\footnotemark.
\end{description}
\footnotetext{Il existe un grand nombre de couleurs prédéfinies dans
\R. On peut récupérer leur liste en utilisant la fonction
\rfunc{colors} en tapant simplement \texttt{colors()} dans la
console, ou en consultant le document suivant~:
\url{http://www.stat.columbia.edu/~tzheng/files/Rcolor.pdf}}
Deux exemples sont donnés figure~\ref{fig_hist2} \vpageref{fig_hist2}
et figure~\ref{fig_hist3} \vpageref{fig_hist3}.
\begin{figure}
<<>>=
hist(d$heures.tv, main="Heures de télé en 7 classes", breaks=7,
xlab="Heures", ylab="Proportion", probability=TRUE, col="orange")
@
\caption{Un autre exemple d'histogramme}
\label{fig_hist2}
\end{figure}
\begin{figure}
<<>>=
hist(d$heures.tv, main="Heures de télé avec classes spécifiées", breaks=c(0,1,4,9,12),
xlab="Heures", ylab="Proportion", col="red")
@
\caption{Encore un autre exemple d'histogramme}
\label{fig_hist3}
\end{figure}
Voir la page d'aide de la fonction \rfunc{hist} pour plus de détails
sur les différentes options.
\subsubsection{Boîtes à moustaches}
Les boîtes à moustaches, ou \rfunc{boxplot} en anglais, sont une
autre représentation graphique de la répartition des valeurs d'une
variable quantitative. Elles sont particulièrement utiles pour
comparer les distributions de plusieurs variables ou d'une même
variable entre différents groupes, mais peuvent aussi être utilisées
pour représenter la dispersion d'une unique variable. La fonction qui
produit ces graphiques est la fonction \rfunc{boxplot}. On trouvera un
exemple figure~\ref{fig_boxplot1} \vpageref{fig_boxplot1}.
\begin{figure}
<<>>=
boxplot(d$heures.tv, main="Nombre d'heures passées devant la télé par jour", ylab="Heures")
@
\caption{Exemple de boîte à moustaches}
\label{fig_boxplot1}
\end{figure}
Comment interpréter ce graphique~? On le comprendra mieux à partir de
la figure~\ref{fig_boxplot2} \vpageref{fig_boxplot2}\footnote{Le code
ayant servi à générer cette figure est une copie quasi conforme de
celui présenté dans l'excellent document de Jean Lobry sur les
graphiques de base avec \R, téléchargeable sur le site du Pôle
bioinformatique lyonnais~:
\url{http://pbil.univ-lyon1.fr/R/pdf/lang04.pdf}.}.
\begin{figure}
<<>>=
boxplot(d$heures.tv, col = grey(0.8), main="Nombre d'heures passées devant la télé par jour", ylab="Heures")
abline(h = median(d$heures.tv, na.rm = TRUE), col = "navy", lty=2)
text(1.35, median(d$heures.tv, na.rm = TRUE)+0.15, "Médiane", col = "navy")
Q1 <- quantile(d$heures.tv, probs = 0.25, na.rm = TRUE)
abline(h = Q1, col = "darkred")
text(1.35, Q1+0.15, "Q1 : premier quartile", col = "darkred", lty=2)
Q3 <- quantile(d$heures.tv, probs = 0.75, na.rm = TRUE)
abline(h = Q3, col = "darkred")
text(1.35, Q3+0.15, "Q3 : troisième quartile", col = "darkred", lty=2)
arrows(x0 = 0.7, y0 = quantile(d$heures.tv, probs = 0.75,
na.rm = TRUE), x1 = 0.7, y1 = quantile(d$heures.tv,
probs = 0.25, na.rm = TRUE), length = 0.1, code = 3)
text(0.7, Q1 + (Q3-Q1)/2+0.15, "h", pos = 2)
mtext("L'écart inter-quartile h contient 50 % des individus", side = 1)
abline(h = Q1 - 1.5 * (Q3 - Q1), col = "darkgreen")
text(1.35, Q1 - 1.5 * (Q3 - Q1) + 0.15, "Q1 -1.5 h", col = "darkgreen", lty=2)
abline(h = Q3 + 1.5 * (Q3 - Q1), col = "darkgreen")
text(1.35, Q3 + 1.5 * (Q3 - Q1) + 0.15, "Q3 +1.5 h", col = "darkgreen", lty=2)
@
\caption{Interprétation d'une boîte à moustaches}
\label{fig_boxplot2}
\end{figure}
Le carré au centre du graphique est délimité par les premiers et
troisième quartiles, avec la médiane représentée par une ligne plus
sombre au milieu. Les <<~fourchettes~>> s'étendant de part et d'autres
vont soit jusqu'à la valeur minimale ou maximale, soit jusqu'à une
valeur approximativement égale au quartile le plus proche plus 1,5
fois l'écart inter-quartile. Les points se situant en-dehors de cette
fourchette sont représentés par des petits ronds et sont généralement
considérés comme des valeurs extrêmes, potentiellement aberrantes.
On peut ajouter la représentation des valeurs sur le graphique pour en
faciliter la lecture avec des petits traits dessinés sur l'axe
vertical (fonction \rfunc{rug}), comme sur la
figure~\ref{fig_boxplotrug} \vpageref{fig_boxplotrug}.
\begin{figure}
<<>>=
boxplot(d$heures.tv, main="Nombre d'heures passées devant la télé par
jour", ylab="Heures")
rug(d$heures.tv, side=2)
@
\caption{Boîte à moustaches avec représentation des valeurs}
\label{fig_boxplotrug}
\end{figure}
\subsection{Variable qualitative}
\subsubsection{Tris à plat}
La fonction la plus utilisée pour le traitement et l'analyse des
variables qualitatives (variable prenant ses valeurs dans un ensemble
de modalités) est sans aucun doute la fonction \rfunc{table}, qui
donne les effectifs de chaque modalité de la variable.
<<>>=
table(d$sexe)
@
La tableau précédent nous indique que parmi nos enquêtés on trouve 899
hommes et 1101 femmes.
Quand le nombre de modalités est élevé, on peut ordonner le tri à plat
selon les effectifs à l'aide de la fonction \rfunc{sort}.
<<>>=
table(d$occup)
sort(table(d$occup))
sort(table(d$occup), decreasing=TRUE)
@
À noter que la fonction \rfunc{table} exclut par défaut les
non-réponses du tableau résultat. L'argument \texttt{useNA} de cette fonction
permet de modifier ce comportement~:
\begin{itemize}
\item avec \texttt{useNA="no"} (valeur par défaut), les valeurs manquantes ne sont
jamais incluses dans le tri à plat~;
\item avec \texttt{useNA="ifany"}, une colonne \texttt{NA} est ajoutée si des
valeurs manquantes sont présentes dans les données~;
\item avec \texttt{useNA="always"}, une colonne \texttt{NA} est toujours
ajoutée, même s'il n'y a pas de valeurs manquantes dans les données.
\end{itemize}
On peut donc utiliser~:
<<>>=
table(d$trav.satisf, useNA="ifany")
@
L'utilisation de \rfunc{summary} permet également l'affichage du tri à plat et
du nombre de non-réponses~:
<<>>=
summary(d$trav.satisf)
@
Pour obtenir un tableau avec la répartition en pourcentages, on peut
utiliser la fonction \rfunc{freq} de \marqr l'extension \textsf{questionr}\footnotemark.
\footnotetext{
En l'absence de l'extension \texttt{questionr}, on pourra se rabattre sur la
fonction \rfunc{prop.table} avec la commande suivante :
\texttt{prop.table(table(d\$qualif))}.
}
<<>>=
freq(d$qualif)
@
La colonne \texttt{n} donne les effectifs bruts, et la colonne
\texttt{\%} la répartition en pourcentages. La fonction accepte
plusieurs paramètres permettant d'afficher les totaux, les pourcentages
cumulés, de trier selon les effectifs ou de contrôler l'affichage. Par
exemple~:
<<>>=
freq(d$qualif, cum=TRUE, total=TRUE, sort="inc", digits=2, exclude=NA)
@
La colonne \texttt{\%cum} indique ici le pourcentage cumulé, ce qui
est ici une très mauvaise idée puisque pour ce type de variable cela
n'a aucun sens. Les lignes du tableau résultat ont été triés par
effectifs croissants, les totaux ont été ajoutés, les non-réponses
exclues, et les pourcentages arrondis à deux décimales.
Pour plus d'informations sur la commande \rfunc{freq}, consultez sa
page d'aide en ligne avec \texttt{?freq} ou \texttt{help("freq")}.
\subsubsection{Représentation graphique}
Pour représenter la répartition des effectifs parmi les modalités
d'une variable qualitative, on a souvent tendance à utiliser des
diagrammes en secteurs (camemberts). Ceci est possible sous \R avec la
fonction \rfunc{pie}, mais la page d'aide de ladite fonction nous le
déconseille assez vivement~: les diagrammes en secteur sont en effet
une mauvaise manière de présenter ce type d'information, car l'\oe{}il
humain préfère comparer des longueurs plutôt que des surfaces\footnotemark.
\footnotetext{On trouvera des exemples illustrant cette idée dans le
document de Jean Lobry cité précédemment.}
On privilégiera donc d'autres formes de représentations, à savoir les
diagrammes en bâtons et les diagrammes de Cleveland.
Les diagrammes en bâtons sont utilisés automatiquement par \R
lorsqu'on applique la fonction générique \rfunc{plot} à un tri à plat
obtenu avec \rfunc{table}. On privilégiera cependant ce type de
représentations pour les variables de type numérique comportant un
nombre fini de valeurs. Le nombre de frères, s\oe{}urs, demi-frères et
demi-s\oe{}urs est un bon exemple, indiqué figure~\ref{fig_barplot}
\vpageref{fig_barplot}.
\begin{figure}
<<>>=
plot(table(d$freres.soeurs), main="Nombre de frères, soeurs, demi-frères et demi-soeurs", ylab="Effectif")
@
\caption{Exemple de diagramme en bâtons}
\label{fig_barplot}
\end{figure}
Pour les autres types de variables qualitatives, on privilégiera les
diagrammes de Cleveland, obtenus avec la fonction \rfunc{dotchart}. On doit
appliquer cette fonction au tri à plat de la variable, obtenu avec la fonction
\rfunc{table}. Le résultat se trouve
figure~\ref{fig_dotchart} \vpageref{fig_dotchart}.
\begin{figure}
<<warning=FALSE>>=
dotchart(table(d$clso), main="Sentiment d'appartenance à une classe sociale", pch=19)
@
\caption{Exemple de diagramme de Cleveland}
\label{fig_dotchart}
\end{figure}
Quand la variable comprend un grand nombre de modalités, il est
préférable d'ordonner le tri à plat obtenu à l'aide de la fonction
\rfunc{sort} (voir figure~\ref{fig_dotchartsort} \vpageref{fig_dotchartsort}).
\begin{figure}
<<warning=FALSE>>=
dotchart(sort(table(d$qualif)), main="Niveau de qualification")
@
\caption{Exemple de diagramme de Cleveland ordonné}
\label{fig_dotchartsort}
\end{figure}
\begin{astuce}
L'agument \texttt{pch}, qui est utilisé par la plupart des graphiques de type
points, permet de spécifier le symbole à utiliser. Il peut prendre soit un
nombre entier compris entre 0 et 25, soit un charactère textuel
(voir figure~\ref{fig_pch} \vpageref{fig_pch}).
\end{astuce}
\begin{figure}
<<figure_pch, echo=FALSE>>=
source("pchShow.R")
pchShow(c("*","+","a","x"),main="", symbolsize=2.5, linewidth=2,fillcolor="palegreen3",symbolcolor="palevioletred3")
@
\caption{Différentes valeurs possibles pour l'argument \texttt{pch}}
\label{fig_pch}
\end{figure}
\section{Exercices}
\begin{exo}{simplescript}
Créer un script qui effectue les actions suvantes et exécutez-le~:
\begin{itemize}
\item charger l'extension \questionr
\item charger le jeu de données \texttt{hdv2003}
\item placer le jeu de données dans un objet nommé \texttt{df}
\item afficher la liste des variables de \texttt{df} et leur type
\end{itemize}
\end{exo}
\begin{exo}{editdf}
Des erreurs se sont produites lors de la saisie des données de
l'enquête. En fait le premier individu du jeu de données n'a pas 42
ans mais seulement 24, et le second individu n'est pas un homme mais
une femme. Corrigez les erreurs et stockez les données corrigées
dans un objet nommé \texttt{df.ok}.
Affichez ensuite les 4 premières lignes de \texttt{df.ok} pour
vérifier que les modifications ont bien été prises en compte.
\end{exo}
\begin{exo}{varquanti}
Nous souhaitons étudier la répartition des âges des enquêtés
(variable \texttt{age}). Pour
cela, affichez les principaux indicateurs de cette
variable. Représentez ensuite sa distribution par un histogramme en
10 classes, puis sous forme de boîte à moustache, et enfin sous la
forme d'un diagramme en bâtons représentant les effectifs de chaque
âge.
\end{exo}
\begin{exo}{varquali}
On s'intéresse maintenant à l'importance accordée par les enquêtés à
leur travail (variable \texttt{trav.imp}). Faites un tri à plat des
effectifs des modalités de cette variable avec la commande
\rfunc{table}. Y'a-t-il des valeurs manquantes~?
Faites un tri à plat affichant à la fois les effectifs et les
pourcentages de chaque modalité.
Représentez graphiquement les effectifs des modalités à l'aide d'un
diagramme de Cleveland.
\end{exo}
\chapter{Import/export de données}
L'import et l'export de données depuis ou vers d'autres applications
est couvert en détail dans l'un des manuels officiels (en anglais)
nommé \textit{R Data Import/Export} et accessible, comme les autres
manuels, à l'adresse suivante~:
\url{http://cran.r-project.org/manuals.html}
Cette partie est très largement tirée de ce document, et on pourra s'y
reporter pour plus de détails.
\begin{important}
Importer des données est souvent l'une des première opérations que
l'on effectue lorsque l'on débute sous \R, et ce n'est pas la moins
compliquée. En cas de problème il ne faut donc pas hésiter à
demander de l'aide par les différents moyens disponibles (voir
partie~\ref{sec_aide} \vpageref{sec_aide}) avant de se
décourager.
\end{important}
\begin{remarque}
Un des points délicats pour l'importation de données dans \R
concerne le nom des variables. Pour être utilisables dans \R ceux-ci
doivent être à la fois courts et explicites, ce qui n'est pas le cas
dans d'autres applications comme \textsf{Modalisa} par exemple. La
plupart des fonctions d'importation s'occupent de convertir les noms
de manières à ce qu'ils soient compatibles avec les règles de \R
(remplacement des espaces par des points par exemple), mais un
renommage est souvent à prévoir, soit au sein de l'application
d'origine, soit une fois les données importées dans \R.
\end{remarque}
\section{Accès aux fichiers et répertoire de travail}
Dans ce qui suit, puisqu'il s'agit d'importer des données externes,
nous allons avoir besoin d'accéder à des fichiers situés sur le disque
dur de notre ordinateur.
Par exemple, la fonction \rfunc{read.table}, très utilisée pour
l'import de fichiers texte, prend comme premier argument le nom du
fichier à importer, ici \texttt{fichier.txt}~:
<<eval=FALSE>>=
donnees <- read.table("fichier.txt")
@
Cependant, ceci ne fonctionnera que si le fichier se trouve dans le
\textit{répertoire de travail} de \R. De quoi s'agit-il~? Tout simplement du
répertoire dans lequel \R est actuellement en train de s'exécuter. Pour savoir
quel est le répertoire de travail actuel, on peut utiliser la fonction
\rfunc{getwd}\footnote{Le résultat indiqué ici correspond à un système
\textsf{Linux}, sous \textsf{Windows} vous devriez avoir quelque chose de la
forme \verb|C:/Documents and Settings/| \ldots}~:
<<>>=
getwd()
@
Si on veut modifier le répertoire de travail, on utilise
\rfunc{setwd} en lui indiquant le chemin complet. Par exemple sous
\textsf{Linux}~:
<<eval=FALSE>>=
setwd("/home/julien/projets/R")
@
Sous \textsf{Windows} le chemin du répertoire est souvent un peu plus
compliqué. Si vous utilisez l'interface graphique par défaut, vous pouvez
utiliser la fonction \textit{Changer le répertoire courant} du menu
\textit{Fichier}. Celle-ci vous permet de sélectionner le répertoire de
travail de la session en cours en le sélectionnant via une boîte de dialogue.
Si vous utilisez \textsf{RStudio}, Vous pouvez utiliser une des commandes \textit{set
working directory} du menu \textit{session} ou, mieux, utiliser les
fonctionnalités de gestion de projet qui vous permettent de mémoriser, projet
par projet, le répertoire de travail, la liste des fichiers ouverts ainsi que
différents paramétrages spécifiques.
Une fois le répertoire de travail fixé, on pourra accéder aux fichiers
qui s'y trouvent directement, en spécifiant seulement leur nom. On
peut aussi créer des sous-répertoires dans le répertoire de travail~;
une potentielle bonne pratique peut être de regrouper tous les
fichiers de données dans un sous-répertoire nommé \texttt{donnees}. On
pourra alors accéder aux fichiers qui s'y trouvent de la manière suivante~:
<<eval=FALSE>>=
donnees <- read.table("donnees/fichier.txt")
@
Dans ce qui suit on supposera que les fichiers à importer se trouvent
directement dans le répertoire de travail, et on n'indiquera donc que
le nom du fichier, sans indication de chemin ou de répertoire
supplémentaire.
\begin{rstudio}
Si vous utilisez l'environnement de développement \textsf{RStudio}, vous
pouvez vous débarasser du problème des répertoires de travail en utilisant sa
fonctionnalité de gestion de \textit{projets}. Les projets sont accessibles
en haut à droite de l'écran. Un projet permet de centraliser tout ses
fichiers dans un même répertoire. De plus, il est très facile de basculer
très rapidement d'un projet à un autre, en retrouvrant sa session de travail
dans l'était où elle était.
\end{rstudio}
\section{Import de données depuis un tableur}
Il est assez courant de vouloir importer des données saisies ou
traitées avec un tableur du type \textsf{OpenOffice/LibreOffice} ou
\textsf{Excel}. En général les données prennent alors la forme d'un
tableau avec les variables en colonne et les individus en ligne.
\begin{center}
\includegraphics[width=0.8\textwidth]{img/donnees_tableur.png}
\end{center}
\subsection{Depuis \textsf{Excel}}
La démarche pour importer ces données dans \R est d'abord de les
enregistrer dans un format de type texte. Sous \textsf{Excel}, on peut
ainsi sélectionner \textit{Fichier}, \textit{Enregistrer sous}, puis
dans la zone \textit{Type de fichier} choisir soit \textit{Texte
(séparateur tabulation)}, soit \textit{CSV (séparateur: point-virgule)}.
\begin{center}
\includegraphics[width=0.8\textwidth]{img/selecteur_fichier_excel.png}
\end{center}
Dans le premier cas, on peut importer le fichier en utilisant la
fonction \rfunc{read.delim2}, de la manière suivante~:
<<eval=FALSE>>=
donnees <- read.delim2("fichier.txt")
@
Dans le second cas, on utilise \rfunc{read.csv2}, de la même manière~:
<<eval=FALSE>>=
donnees <- read.csv2("fichier.csv")
@
\subsection{Depuis \textsf{OpenOffice} ou \textsf{LibreOffice}}
Depuis \textsf{OpenOffice} on procédera de la même manière, en
sélectionnant le type de fichier \textit{Texte CSV}.
\begin{center}
\includegraphics[width=0.8\textwidth]{img/selecteur_fichier_ooo.png}
\end{center}
On importe ensuite les données dans \R à l'aide de la fonction
\rfunc{read.csv}~:
<<eval=FALSE>>=
read.csv("fichier.csv", dec=",")
@
\subsection{Autres sources / en cas de problèmes}
Les fonctions \rfunc{read.csv} et compagnie sont en fait des dérivées
de la fonction plus générique \rfunc{read.table}. Celle-ci contient
de nombreuses options permettant d'adapter l'import au format du
fichier texte. On pourra se reporter à la page d'aide de
\rfunc{read.table} si on recontre des problèmes ou si on souhaite
importer des fichiers d'autres sources.
Parmi les options disponibles, on citera notamment~:
\begin{description}
\item[\texttt{header}] indique si la première ligne du fichier
contient les noms des variables (valeur \texttt{TRUE}) ou non
(valeur \texttt{FALSE}).
\item[\texttt{sep}] indique le caractère séparant les champs. En
général soit une virgule, soit un point-virgule, soit une
tabulation. Pour cette dernière l'option est
\texttt{sep="\textbackslash{}t"}.
\item[\texttt{quote}] indique le caractère utilisé pour délimiter les
champs. En général on utilise soit des guillemets doubles
(\texttt{quote="\textbackslash{}""}) soit rien du tout
(\texttt{quote=""}).
\item[\texttt{dec}] indique quel est le caractère utilisé pour séparer
les nombres et leurs décimales. Il s'agit le plus souvent de la
virgule lorsque les données sont en français
(\texttt{dec=","}), et le point pour les données anglophones
(\texttt{dec="."}).
\end{description}
D'autres options sont disponibles, pour gérer le format d'encodage du
fichier source ou de nombreux autres paramètres d'importation. On se
réfèrera alors à la page d'aide de \rfunc{read.table} et à la section
\textit{Spreadsheet-like data} de \textit{R Data Import/Export}~:
\url{http://cran.r-project.org/doc/manuals/R-data.html#Spreadsheet_002dlike-data}
\section{Import depuis d'autres logiciels}
La plupart des fonctions permettant l'import de fichiers de données
issus d'autres logiciels font partie d'une extension nommée
\textsf{foreign}, présente à l'installation de \R mais qu'il est
nécessaire de charger en mémoire avant utilisation avec l'instruction~:
<<eval=FALSE>>=
library(foreign)
@
\subsection{\textsf{SAS}}
Les fichiers au format \textsf{SAS} se présentent en général sous deux
format~: format \textsf{SAS} export (extension \texttt{.xport} ou
\texttt{.xpt}) ou format \textsf{SAS} natif (extension \texttt{.sas7bdat}).
\R peut lire directement les fichiers au format export \textit{via} la fonction
\rfunc{read.xport} de l'extension \textsf{foreign}.
Celle-ci s'utilise très simplement, en lui passant le nom du fichier
en argument~:
<<eval=FALSE>>=
donnees <- read.xport("fichier.xpt")
@
En ce qui concerne les fichiers au format \textsf{SAS} natif, on pourra utiliser la fonction \rfunc{read\_sas} de l'extension \texttt{haven}. Celle-ci est capable de lire directement les fichiers au format \texttt{sas7bdat} et \texttt{sas7bcat} :
<<eval=FALSE>>=
library(haven)
donnees <- read_sas("fichier.sas7bdat")
@
\subsection{\textsf{SPSS}}
Les fichiers générés par \textsf{SPSS} sont accessibles depuis \R avec
la fonction \rfunc{read.spss} de l'extension
\texttt{foreign}. Celle-ci peut lire aussi bien les fichiers
sauvegardés avec la fonction \textit{Enregistrer} que ceux générés par
la fonction \textit{Exporter}.
La syntaxe est également très simple~:
<<eval=FALSE>>=
donnees <- read.spss("fichier.sav", to.data.frame = TRUE)
@
Plusieurs options permettant de contrôler l'importation des données
sont disponibles. On se reportera à la page d'aide de la fonction pour
plus d'informations. Il est vivement recommandé d'utiliser systématiquement
l'option \texttt{to.data.frame=TRUE}.
Une alternative est fournie par l'extension \texttt{haven} et ses fonctions \rfunc{read\_por} et \rfunc{read\_sav}.
\subsection{\textsf{Stata}}
Les fichiers générés par \textsf{Stata} sont accessibles depuis \R avec
la fonction \rfunc{read.dta} de l'extension
\texttt{foreign}.
La syntaxe est également très simple~:
<<eval=FALSE>>=
donnees <- read.data("fichier.dta", to.data.frame = TRUE)
@
\begin{astuce}
L'importation des dates est parfois mal gérées. Dans ces cas là, l'opération
suivante peut fonctionner. Sans garantie néanmoins, il est toujours vivement
conseillé de vérifier le résultat obtenu !
\texttt{donnees\$date <- as.Date(donnees\$Date/(1000*3600*24), origin='1960-01-01')}
\end{astuce}
\subsection{Fichiers \texttt{dbf}}
L'Insee diffuse ses fichiers détails depuis son site Web au format
\textsf{dBase} (extension \texttt{.dbf}). Ceux-ci sont directement lisibles
dans \R avec la fonction \rfunc{read.dbf} de l'extension \texttt{foreign}.
<<eval=FALSE>>=
donnees <- read.dbf("fichier.dbf")
@
La principale limitation des fichiers \texttt{dbf} est de ne pas gérer
plus de 256 colonnes. Les tables des enquêtes de l'Insee sont donc
parfois découpées en plusieurs fichiers \texttt{dbf} qu'il convient de
fusionner avec la fonction \rfunc{merge}. L'utilisation de cette
fonction est détaillée dans la section~\ref{sec_merge}
\vpageref{sec_merge}.
\section{Autres sources}
\R offre de très nombreuses autres possibilités pour accéder aux
données. Il est ainsi possible d'importer des données depuis d'autres
applications qui n'ont pas été évoquées (\textsf{Epi Info},
\textsf{S-Plus}, etc.), de se connecter à un système de base de
données relationelle type \textsf{MySql}, de lire des données
\textit{via} \texttt{ODBC} ou des connexions réseau, etc.
Pour plus d'informations on consultera le manuel \textit{R Data Import/Export}~:
\url{http://cran.r-project.org/manuals.html}
\section{Sauver ses données}
\R dispose également de son propre format pour sauvegarder et échanger des
données. On peut sauver n'importe quel objet créé avec \R et il est possible de
sauver plusieurs objets dans un même fichier. L'usage est d'utiliser l'extension
\texttt{.RData} pour les fichiers de données \R. La fonction à utiliser
s'appelle tout simplement \rfunc{save}.
Par exemple, si l'on souhaite sauvegarder son tableau de données \texttt{d}
ainsi que les objets \texttt{tailles} et \texttt{poids} dans un fichier
\texttt{export.RData} :
<<eval=FALSE>>=
save(d,tailles,poids,file="export.RData")
@
À tout moment, il sera toujours possible de recharger ces données en mémoire à
l'aide de la fonction \rfunc{load} :
<<eval=FALSE>>=
load("export.RData")
@
\begin{important}
Si entre temps vous aviez modifié votre tableau \texttt{d}, vos modifications
seront perdues. En effet, si lors du chargement de données, un objet du même
nom existe en mémoire, ce dernier sera remplacé par l'objet importé.
\end{important}
La fonction \rfunc{save.image} est un raccourci pour sauvergarder tous les
objets de la session de travail dans le fichier \texttt{.RData} (un fichier un
peu étrange car il n'a pas de nom mais juste une extension). Lors de la
fermeture de \R ou de \textsf{RStudio}, il vous sera demandé si vous souhaitez
enregistrer votre session. Si vous répondez \textit{Oui}, c'est cette fonction
\rfunc{save.image} qui sera appliquée.
<<eval=FALSE>>=
save.image()
@
\section{Exporter des données}
\R propose également différentes fonctions permettant d'exporter des
données vers des formats variés.
\begin{itemize}
\item \rfunc{write.table} est l'équivalent de \rfunc{read.table} et
permet d'enregistrer des tableaux de données au format texte, avec
de nombreuses options~;
\item \rfunc{write.foreign}, de l'extension \texttt{foreign}, permet
d'exporter des données aux formats \textsf{SAS}, \textsf{SPSS} ou
\textsf{Stata}~;
\item \rfunc{write.dbf}, de l'extension \texttt{foreign}, permet
d'exporter des données au format \textsf{dBase}~;
\end{itemize}
À nouveau, pour plus de détails on se référera aux pages d'aide de ces
fonctions et au manuel \textit{R Data Import/Export}.
\section{Exercices}
\begin{exo}{import_tableur}
Saisissez quelques données fictives dans une application de type
tableur, enregistrez-les dans un format texte et importez-les dans
\R.
Vérifiez que l'importation s'est bien déroulée.
\end{exo}
\begin{exo}{import_dbf}
L'adresse suivante permet de télécharger un fichier au format
\textsf{dBase} contenant une partie des données de l'enquête
\textit{EPCV Vie associative} de l'INSEE (2002)~:
\url{http://telechargement.insee.fr/fichiersdetail/epcv1002/dbase/epcv1002_BENEVOLAT_dbase.zip}
Téléchargez le fichier, décompressez-le et importez les données dans \R.
\end{exo}
\chapter{Manipulation de données}
\begin{important}
Cette partie est un peu aride et pas forcément très intuitive. Elle
aborde cependant la base de tous les traitements et manipulation de
données sous \R, et mérite donc qu'on s'y arrête un moment, ou qu'on
y revienne un peu plus tard en cas de saturation\ldots
\end{important}
\section{Variables}
Le type d'objet utilisé par \R pour stocker des tableaux de données
s'appelle un \textit{data frame}. Celui-ci comporte des observations
en ligne et des variables en colonnes. On accède aux variables d'un
\textit{data frame} avec l'opérateur \rfunc{\$}.
Dans ce qui suit on travaillera sur le jeu de données tiré de
l'enquête \textit{Histoire de vie}, fourni avec l'extension \questionr et
décrit dans l'annexe~\ref{sec_hdv2003}, page~\pageref{sec_hdv2003}.
<<eval=FALSE>>=
library(questionr)
data(hdv2003)
d <- hdv2003
@
Mais aussi sur le jeu de données tiré du recensement 1999, décrit
\vpageref{sec_rp99}~:
<<>>=
data(rp99)
@
\subsection{Types de variables}
On peut considérer qu'il existe quatre type de variables dans \R~:
\begin{itemize}
\item les variables \textbf{numériques}, ou quantitatives~;
\item les \textbf{facteurs}, qui prennent leurs valeurs dans un
ensemble défini de modalités. Elles correspondent en général aux
questions fermées d'un questionnaire~;
\item les variables \textbf{caractères}, qui contiennent des chaînes de
caractères plus ou moins longues. On les utilise pour les questions
ouvertes ou les champs libres~;
\item les variables \textbf{booléennes}, qui ne peuvent prendre que la
valeur \textit{vrai} (\texttt{TRUE}) ou \textit{faux}
(\texttt{FALSE}). On les utilise dans \R pour les calculs et les
recodages.
\end{itemize}
Pour connaître le type d'une variable donnée, on peut utiliser la
fonction \rfunc{class}.
\begin{center}
\begin{tabular}{ll}
\textbf{Résultat de \rfunc{class}} & \textbf{Type de variable} \\
\hline
\texttt{factor} & Facteur \\
\texttt{integer} & Numérique \\
\texttt{double} & Numérique \\
\texttt{numeric} & Numérique \\
\texttt{character} & Caractères \\
\texttt{logical} & Booléenne \\
\end{tabular}
\end{center}
<<>>=
class(d$age)
class(d$sexe)
class(c(TRUE,TRUE,FALSE))
@
La fonction \rfunc{str} permet également d'avoir un listing de toutes
les variables d'un tableau de données et indique le type de chacune
d'elle.
\subsection{Renommer des variables}
Une opération courante lorsqu'on a importé des variables depuis une
source de données externe consiste à renommer les variables
importées. Sous \R les noms de variables doivent être à la fois courts
et explicites tout en obéissant à certaines règles décrites dans la
remarque \vpageref{rq_noms}.
On peut lister les noms des variables d'un \textit{data frame} à
l'aide de la fonction \rfunc{names}~:
<<>>=
names(d)
@
Cette fonction peut également être utilisée pour renommer l'ensemble
des variables. Si par exemple on souhaitait passer les noms de toutes
les variables en majuscules, on pourrait faire~:
<<>>=
d.maj <- d
names(d.maj) <- c("ID", "AGE", "SEXE", "NIVETUD", "POIDS", "OCCUP", "QUALIF",
"FRERES.SOEURS", "CLSO", "RELIG", "TRAV.IMP", "TRAV.SATISF",
"HARD.ROCK", "LECTURE.BD", "PECHE.CHASSE", "CUISINE", "BRICOL",
"CINEMA", "SPORT", "HEURES.TV")
summary(d.maj$SEXE)
@
Ce type de renommage peut être utile lorsqu'on souhaite passer en
revue tous les noms de variables d'un fichier importé pour les
corriger le cas échéant. Pour faciliter un peu ce travail pas
forcément passionant, on peut utiliser la fonction \rfunc{dput}~:
<<>>=
dput(names(d))
@
On obtient en résultat la liste des variables sous forme de vecteur
déclaré. On n'a plus alors qu'à copier/coller cette chaîne, rajouter
\texttt{names(d) <- } devant, et modifier un à un les noms des variables.
Si on souhaite seulement modifier le nom d'une variable, on peut
utiliser la fonction \rfunc{rename.variable} de \marqr l'extension
\questionr. Celle-ci prend en argument le tableau de données, le nom actuel
de la variable et le nouveau nom. Par exemple, si on veut renommer la
variable \texttt{bricol} du tableau de données \texttt{d} en
\texttt{bricolage}~:
<<>>=
d <- rename.variable(d, "bricol", "bricolage")
table(d$bricolage)
@
<<echo=FALSE,results="hide">>=
d <- rename.variable(d, "bricolage", "bricol")
@
\subsection{Facteurs}
\label{sec_factor}
Parmi les différents types de variables, les \textit{facteurs}
(\texttt{factor}) sont à la fois à part et très utilisés, car ils vont
correspondre à la plupart des variables issues d'une question fermée
dans un questionnaire.
Les facteurs prennent leurs valeurs dans un ensemble de modalités
prédéfinies, et ne peuvent en prendre d'autres. La liste des valeurs
possibles est donnée par la fonction \rfunc{levels}~:
<<>>=
levels(d$sexe)
@
Si on veut modifier la valeur du sexe du premier individu de notre
tableau de données avec une valeur différente, on obient un message
d'erreur et une valeur manquante est utilisée à la place~:
<<>>=
d$sexe[1] <- "Chihuahua"
d$sexe[1]
@
<<results="hide",echo=FALSE>>=
d <- hdv2003
@
On peut très facilement créer un facteur à partir d'une variable de
type caractères avec la commande \rfunc{factor}~:
<<>>=
v <- factor(c("H","H","F","H"))
v
@
Par défaut, les niveaux d'un facteur nouvellement créés sont
l'ensemble des valeurs de la variable caractères, ordonnées par ordre
alphabétique. Cette ordre des niveaux est utilisé à chaque fois qu'on
utilise des fonctions comme \rfunc{table}, par exemple~:
<<>>=
table(v)
@
On peut modifier cet ordre au moment de la création du facteur en
utilisant l'option \texttt{levels}~:
<<>>=
v <- factor(c("H","H","F","H"), levels=c("H","F"))
table(v)
@
On peut aussi modifier l'ordre des niveaux d'une variable déjà existante~:
<<>>=
d$qualif <- factor(d$qualif, levels=c("Ouvrier specialise", "Ouvrier qualifie", "Employe", "Technicien",
"Profession intermediaire", "Cadre", "Autre"))
table(d$qualif)
@
\subsubsection{Interface interactive}
L'extension \questionr \marqr propose une interface interactive pour le
réordonnancement des niveaux d'un facteur. Cette fonction, nommée
\rfunc{iorder}, vous permet de réordonner les modalités de manière graphique
et de générer le code R correspondant.
Vous pouvez lancer \rfunc{iorder} directement depuis un script ou la console. Dans l'exemple précédent, vous pouvez exécuter :
<<launchiorder, eval=FALSE>>=
iorder(d$qualif)
@
Avec une version récente de RStudio, vous pouvez également sélectionner le menu \textit{Addins}, puis choisir \textit{Levels ordering}.
Dans les deux cas, une interface semblable à celle de la figure~\ref{fig_interface_iorder}, \vpageref{fig_interface_iorder} devrait s'afficher soit directement dans RStudio, soit dans votre navigateur Web.
\begin{figure}
\begin{center}
\includegraphics[width=0.65\textwidth]{img/interface_iorder.png}
\end{center}
\caption{Interface de la commande \texttt{iorder}}
\label{fig_interface_iorder}
\end{figure}
Vous pouvez alors choisir la variable à réordonner dans l'onglet \textit{Variable et paramètres}, déplacer les modalités par glisser-déposer dans l'onglet \textit{Réordonner}, et vérifier le
résultat dans l'onglet \textit{Code et résultat}. Une fois le résultat satisfaisant,
cliquez sur \textit{Done} : si vous êtes sous RStudio le code généré sera directement inséré dans votre script actuel à l'emplacement du curseur. Sinon, ce code sera affiché dans la console et vous pourrez le copier/coller pour l'inclure dans votre script\footnotemark.
\footnotetext{Le fonctionnement des interfaces interactives de \questionr est
décrit plus en détail section~\ref{sec_interfaces}, \vpageref{sec_interfaces}.}
On peut également modifier les niveaux eux-mêmes. Imaginons que l'on souhaite
créer une nouvelle variable \texttt{qualif.abr} contenant les noms abrégés des
catégories socioprofessionnelles de \texttt{qualif}. On peut alors procéder
comme suit~:
<<r factorlabels>>=
d$qualif.abr <- factor(d$qualif,
levels=c("Ouvrier specialise", "Ouvrier qualifie", "Employe", "Technicien",
"Profession intermediaire", "Cadre", "Autre"),
labels=c("OS","OQ","Empl","Tech","Interm","Cadre","Autre"))
table(d$qualif.abr)
@
Dans ce qui précède, le paramètre \texttt{levels} de \rfunc{factor} permet de
spécifier quels sont les niveaux retenus dans le facteur résultat, ainsi que
leur ordre. Le paramètre \texttt{labels}, lui, permet de modifier les noms de
ces niveaux dans le facteur résultat. Il est donc capital d'indiquer les noms
de \texttt{labels} exactement dans le même ordre que les niveaux de
\texttt{levels}. Pour s'assurer de ne pas avoir commis d'erreur, il est
recommandé d'effectuer un tableau croisé entre l'ancien et le nouveau facteur~:
<<r factorcrosstabverif>>=
table(d$qualif, d$qualif.abr)
@
On a donc ici un premier moyen d'effectuer un recodage des modalités d'une
variable de type facteur. D'autres méthodes existent, elles sont notamment
détaillées section~\ref{sec_recodages} \vpageref{sec_recodages}.
À noter que par défaut, les valeurs manquantes ne sont pas considérées comme un
niveau de facteur. On peut cependant les transformer en niveau en
utilisant la fonction \rfunc{addNA}. Ceci signifie cependant
qu'elle ne seront plus considérées comme manquantes par \R~:
<<>>=
summary(d$trav.satisf)
summary(addNA(d$trav.satisf))
@
\section{Indexation}
\label{sec_indexation}
L'indexation est l'une des fonctionnalités les plus puissantes mais
aussi les plus difficiles à maîtriser de \R. Il s'agit d'opérations
permettant de sélectionner des sous-ensembles d'observations et/ou de
variables en fonction de différents critères. L'indexation peut porter
sur des vecteurs, des matrices ou des tableaux de données.
Le principe est toujours le même~: on indique, entre crochets et à la
suite du nom de l'objet à indexer, une série de conditions indiquant
ce que l'on garde ou non. Ces conditions peuvent être de différents
types.
\subsection{Indexation directe}
Le mode le plus simple d'indexation consiste à indiquer la position
des éléments à conserver. Dans le cas d'un vecteur cela permet de
sélectionner un ou plusieurs éléments de ce vecteur.
Soit le vecteur suivant~:
<<>>=
v <- c("a","b","c","d","e","f","g")
@
Si on souhaite le premier élément du vecteur, on peut faire~:
<<>>=
v[1]
@
Si on souhaite les trois premiers éléments ou les éléments 2, 6 et 7~:
<<>>=
v[1:3]
v[c(2,6,7)]
@
Si on veut le dernier élément~:
<<>>=
v[length(v)]
@
Dans le cas de matrices ou de tableaux de données, l'indexation prend
deux arguments séparés par une virgule~: le premier concerne les
\textit{lignes} et le second les \textit{colonnes}. Ainsi, si on veut
l'élément correspondant à la troisième ligne et à la cinquième colonne
du tableau de données \texttt{d}~:
<<>>=
d[3,5]
@
On peut également indiquer des vecteurs~:
<<>>=
d[1:3,1:2]
@
Si on laisse l'un des deux critères vides, on sélectionne
l'intégralité des lignes ou des colonnes. Ainsi si l'on veut seulement
la cinquième colonne ou les deux premières lignes~:
<<>>=
d[,5]
d[1:2,]
@
Enfin, si on préfixe les arguments avec le signe <<~\texttt{-}~>>, ceci
signifie <<~tous les éléments sauf ceux indiqués~>>. Si par exemple on
veut tous les éléments de \texttt{v} sauf le premier~:
<<>>=
v[-1]
@
Bien sûr, tous ces critères se combinent et on peut stocker le
résultat dans un nouvel objet. Dans cet exemple \texttt{d2} contiendra
les trois premières lignes de \texttt{d} mais sans les colonnes 2, 6
et 8.
<<>>=
d2 <- d[1:3, -c(2,6,8)]
@
\subsection{Indexation par nom}
Un autre mode d'indexation consiste à fournir non pas un numéro mais
un nom sous forme de chaîne de caractères. On l'utilise couramment
pour sélectionner les variables d'un tableau de données. Ainsi, les
deux fonctions suivantes sont équivalentes\footnotemark~:
<<>>=
d$clso
d[,"clso"]
@
\footnotetext{Une différence entre les deux est que \texttt{\$} admet une
correspondance partielle du nom de variable, si celle-ci est unique. Ainsi,
\texttt{d\$cls} renverra bien la variable \texttt{clso}, tandis que
\texttt{d\$c} renverra \texttt{NULL}, du fait que plusieurs variables de
\texttt{d} commencent par \texttt{c}.}
Là aussi on peut utiliser un vecteur pour sélectionner plusieurs noms
et récupérer un <<~sous-tableau~>> de données~:
<<>>=
d2 <- d[,c("id","sexe","age")]
@
Les noms peuvent également être utilisés pour les observations
(lignes) d'un tableau de données si celles-ci ont été munies d'un nom
avec la fonction \rfunc{row.names}. Par défaut les noms de ligne sont
leur numéro d'ordre, mais on peut leur assigner comme nom la valeur
d'une variable d'identifiant. Ainsi, on peut assigner aux lignes du
jeu de données \texttt{rp99} le nom des communes correspondantes~:
<<>>=
row.names(rp99) <- rp99$nom
@
On peut alors accéder directement aux communes en donnant leur nom~:
<<>>=
rp99[c("VILLEURBANNE","OULLINS"),]
@
Par contre il n'est pas possible d'utiliser directement l'opérateur
<<~\texttt{-}~>> comme pour l'indexation directe. Pour exclure une colunne en
fonction de son nom, on doit uiliser une autre forme d'indexation,
\textit{l'indexation par condition}, expliquée dans la section suivante. On
peut ainsi faire~:
<<>>=
d2 <- d[, names(d) != "qualif"]
@
Pour sélectionner toutes les colonnes sauf celle qui s'appelle
\texttt{qualif}.
\subsection{Indexation par conditions}
\subsubsection{Tests et conditions}
Une condition est une expression logique dont le résultat est soit
\texttt{TRUE} (vrai) soit \texttt{FALSE} (faux).
Une condition comprend la plupart du temps un opérateur de
comparaison. Les plus courants sont les suivants~:
\begin{center}
\begin{tabular}{cl}
\textbf{Opérateur} & \textbf{Signification} \\
\hline
\rfunc{==} & égal à \\
\texttt{!=}\index{"!=@\texttt{"!=}} & différent de \\
\rfunc{>} & strictement supérieur à \\
\rfunc{<} & strictement inférieur à \\
\rfunc{>=} & supérieur ou égal à \\
\rfunc{<=} & inférieur ou égal à \\
\end{tabular}
\end{center}
Voyons tout de suite un exemple~:
<<>>=
d$sexe == "Homme"
@
Que s'est-il passé~? Nous avons fourni à \R une condition qui signifie
<<~la valeur de la variable \texttt{sexe} vaut "Homme"~>>. Et il nous
a renvoyé un vecteur avec autant d'éléments qu'il y'a d'observations
dans \texttt{d}, et dont la valeur est \texttt{TRUE} si l'observation
correspond à un homme, et \texttt{FALSE} dans les autres cas.
Prenons un autre exemple. On n'affichera cette fois que les premiers
éléments de notre variable d'intérêt à l'aide de la fonction \rfunc{head}~:
<<>>=
head(d$age)
head(d$age>40)
@
On voit bien ici qu'à chaque élément du vecteur \texttt{d\$age} dont la
valeur est supérieure à 40 correspond un élément \texttt{TRUE} dans le
résultat de la condition.
On peut combiner ou modifier des conditions à l'aide des opérateurs
logiques habituels~:
\begin{center}
\begin{tabular}{cl}
\textbf{Opérateur} & \textbf{Signification} \\
\hline
\rfunc{\&} & et logique \\
\rfunc{|} & ou logique \\
\texttt{!}\index{"!@\texttt{"!}} & négation logique \\
\end{tabular}
\end{center}
Comment les utilise-t-on~? Voyons tout de suite des
exemples. Supposons que je veuille déterminer quels sont dans mon
échantillon les hommes ouvriers spécialisés~:
<<>>=
d$sexe=="Homme" & d$qualif=="Ouvrier specialise"
@
Si je souhaite identifier les personnes qui bricolent ou qui font la
cuisine~:
<<>>=
d$bricol=="Oui" | d$cuisine=="Oui"
@
Si je souhaite isoler les femmes qui ont entre 20 et 34 ans~:
<<>>=
d$sexe=="Femme" & d$age>=20 & d$age <=34
@
Si je souhaite récupérer les enquêtés qui ne sont pas cadres, on peut
utiliser l'une des deux formes suivantes~:
<<>>=
d$qualif != "Cadre"
!(d$qualif == "Cadre")
@
Lorsqu'on mélange <<~et~>> et <<~ou~>> il est nécessaire d'utiliser des
parenthèses pour différencier les blocs. La condition suivante
identifie les femmes qui sont soit cadre, soit employée~:
<<>>=
d$sexe=="Femme" & (d$qualif=="Employe" | d$qualif=="Cadre")
@
L'opérateur \rfunc{\%in\%} peut être très utile~: il teste si une
valeur fait partie des éléments d'un vecteur. Ainsi on pourrait
remplacer la condition précédente par~:
<<>>=
d$sexe=="Femme" & d$qualif %in% c("Employe", "Cadre")
@
Enfin, signalons qu'on peut utiliser les fonctions \rfunc{table} ou
\rfunc{summary} pour avoir une idée du résultat de notre condition~:
<<>>=
table(d$sexe)
table(d$sexe == "Homme")
summary(d$sexe == "Homme")
@
\subsubsection{Utilisation pour l'indexation}
L'utilisation des conditions pour l'indexation est assez simple~: si
on indexe un vecteur avec un vecteur booléen, seuls les éléments
correspondant à \texttt{TRUE} seront conservés.
Ainsi, si on fait~:
<<>>=
dh <- d[d$sexe == "Homme", ]
@
On obtiendra un nouveau tableau de données comportant l'ensemble des
variables de \texttt{d}, mais seulement les observations pour
lesquelles \texttt{d\$sexe} vaut <<~Homme~>>.
La plupart du temps ce type d'indexation s'applique aux lignes, mais
on peut aussi l'utiliser sur les colonnes d'un tableau de données.
L'exemple suivant, un peu compliqué, sélectionne uniquement les
variables dont le nom commence par \texttt{a} ou \texttt{s}~:
<<>>=
d[, substr(names(d),0,1) %in% c("a", "s")]
@
On peut évidemment combiner les différents type
d'indexation. L'exemple suivant sélectionne les femmes de plus de 40
ans et ne conserve que les variables \texttt{qualif} et \texttt{bricol}.
<<>>=
d2 <- d[d$sexe=="Femme" & d$age > 40, c("qualif", "bricol")]
@
\subsubsection{Valeurs manquantes dans les conditions}
Une remarque importante~: quand l'un des termes d'une condition
comporte une valeur manquante (\texttt{NA}), le résultat de cette
condition n'est pas toujours \texttt{TRUE} ou \texttt{FALSE}, il peut
aussi être à son tour une valeur manquante.
<<>>=
v <- c(1:5,NA)
v
v > 3
@
On voit que le test \texttt{NA > 3} ne renvoie ni vrai ni faux, mais
\texttt{NA}.
Le résultat d'une condition peut donc comporter un grand nombre de
valeurs manquantes~:
<<>>=
summary(d$trav.satisf=="Satisfaction")
@
Une autre conséquence importante de ce comportement est qu'on ne peut
pas utiliser l'opérateur \texttt{== NA} pour tester la présence de
valeurs manquantes. On utilisera à la place la fonction \textit{ad
hoc} \rfunc{is.na}.
On comprendra mieux le problème avec l'exemple suivant~:
<<>>=
v <- c(1, NA)
v
v == NA
is.na(v)
@
Pour compliquer encore un peu le tout, lorsqu'on utilise une condition pour
l'indexation, si la condition renvoie \texttt{NA}, \R ne sélectionne pas
l'élément mais retourne quand même la valeur \texttt{NA}. Ceci aura donc des
conséquences pour l'extraction de sous-populations, comme indiqué
section~\ref{sec_souspopNA} \vpageref{sec_souspopNA}.
\subsection{Indexation et assignation}
Dans tous les exemples précédents, on a utilisé l'indexation pour
extraire une partie d'un vecteur ou d'un tableau de données, en
plaçant l'opération d'indexation à droite de l'opérateur \texttt{<-}.
Mais l'indexation peut également être placée à gauche de cet
opérateur. Dans ce cas, les éléments sélectionnés par l'indexation
sont alors remplacés par les valeurs indiquées à droite de
l'opérateur \texttt{<-}.
Ceci est parfaitement incompréhensible. Prenons donc un exemple
simple~:
<<>>=
v <- 1:5
v
v[1] <- 3
v
@
Cette fois, au lieu d'utiliser quelque chose comme \texttt{x <- v[1]},
qui aurait placé la valeur du premier élément de \texttt{v} dans
\texttt{x}, on a utilisé \texttt{v[1] <- 3}, ce qui a \textit{mis à
jour} le premier élément de \texttt{v} avec la valeur 3.
Ceci fonctionne également pour les tableaux de données et pour les
différents types d'indexation évoqués précédemment~:
<<>>=
d[257, "sexe"] <- "Homme"
@
Enfin on peut modifier plusieurs éléments d'un seul coup soit en
fournissant un vecteur, soit en profitant du mécanisme de
recyclage. Les deux commandes suivantes sont ainsi rigoureusement
équivalentes~:
<<>>=
d[c(257,438,889), "sexe"] <- c("Homme", "Homme", "Homme")
d[c(257,438,889), "sexe"] <- "Homme"
@
On commence à voir comment l'utilisation de l'indexation par
conditions et de l'assignation va nous permettre de faire des recodages.
<<>>=
d$age[d$age >= 20 & d$age <= 30] <- "20-30 ans"
d$age[is.na(d$age)] <- "Inconnu"
@
\section{Sous-populations}
<<echo=FALSE, results="hide">>=
d <- hdv2003
@
\subsection{Par indexation}
La première manière de construire des sous-populations est d'utiliser
l'indexation par conditions. On peut ainsi facilement sélectionner une
partie des observations suivant un ou plusieurs critères et placer le
résultat dans un nouveau tableau de données.
Par exemple si on souhaite isoler les hommes et les femmes~:
<<>>=
dh <- d[d$sexe=="Homme",]
df <- d[d$sexe=="Femme",]
table(d$sexe)
dim(dh)
dim(df)
@
On a à partir de là trois tableaux de données, \texttt{d} comportant la
population totale, \texttt{dh} seulement les hommes et \texttt{df}
seulement les femmes.
On peut évidemment combiner plusieurs critères~:
<<>>=
dh.25 <- d[d$sexe=="Homme" & d$age <=25, ]
dim(dh.25)
@
\label{sec_souspopNA}
Si on utilise directement l'indexation, il convient cependant d'être
extrêmement prudent avec les valeurs manquantes. Comme indiqué
précédemment, la présence d'une valeur manquante dans une condition
fait que celle-ci est évaluée en \texttt{NA} et qu'au final la ligne
correspondante est conservée par l'indexation~:
<<>>=
summary(d$trav.satisf)
d.satisf <- d[d$trav.satisf=="Satisfaction", ]
dim(d.satisf)
@
Comme on le voit, ici \texttt{d.satisf} contient les individus ayant
la modalité \textit{Satisfaction} mais aussi ceux ayant une valeur
manquante \texttt{NA}. C'est pourquoi il faut toujours soit vérifier
au préalable qu'on n'a pas de valeurs manquantes dans les variables de
la condition, soit exclure explicitement les \texttt{NA} de la manière suivante~:
<<>>=
d.satisf <- d[d$trav.satisf=="Satisfaction" & !is.na(d$trav.satisf), ]
dim(d.satisf)
@
C'est notamment pour cette raison qu'on préfèrera le plus souvent
utiliser la fonction \rfunc{subset}.
\subsection{Fonction \rfunc{subset}}
La fonction \rfunc{subset} permet d'extraire des sous-populations de
manière plus simple et un peu plus intuitive que l'indexation directe.
Celle-ci prend trois arguments principaux~:
\begin{itemize}
\item le nom de l'objet de départ~;
\item une condition sur les observations (\texttt{subset})~;
\item éventuellement une condition sur les colonnes
(\texttt{select}).
\end{itemize}
Reprenons tout de suite un exemple déjà vu~:
<<>>=
dh <- subset(d, sexe=="Homme")
df <- subset(d, sexe=="Femme")
@
L'utilisation de \rfunc{subset} présente plusieurs avantages. Le
premier est d'économiser quelques touches. On n'est en effet pas
obligé de saisir le nom du tableau de données dans la condition sur
les lignes. Ainsi les deux commandes suivantes sont équivalentes~:
<<>>=
dh <- subset(d, d$sexe=="Homme")
dh <- subset(d, sexe=="Homme")
@
Le second avantage est que \rfunc{subset} s'occupe du problème des
valeurs manquantes évoquées précédemment et les exclut de lui-même,
contrairement au comportement par défaut~:
<<>>=
summary(d$trav.satisf)
d.satisf <- d[d$trav.satisf=="Satisfaction", ]
dim(d.satisf)
d.satisf <- subset(d, trav.satisf=="Satisfaction")
dim(d.satisf)
@
Enfin, l'utilisation de l'argument \texttt{select} est simplifié pour
l'expression de condition sur les colonnes. On peut ainsi spécifier
les noms de variable sans guillemets et leur appliquer directement
l'opérateur d'exclusion \texttt{-}~:
<<>>=
d2 <- subset(d, select=c(sexe, sport))
d2 <- subset(d, age > 25, select=-c(id, age, bricol))
@
\subsection{Fonction \rfunc{tapply}}
\label{sec_tapply}
\begin{remarque}
Cette section documente une fonction qui peut être très utile, mais
pas forcément indispensable au départ. Vous pouvez donc passer directement à la suite si vous le souhaitez.
\end{remarque}
La fonction \rfunc{tapply} n'est qu'indirectement liée à la notion de
sous-population, mais peut permettre d'éviter d'avoir à créer ces
sous-populations dans certains cas.
Son fonctionnement est assez simple, mais pas forcément intuitif. La
fonction prend trois arguments~: un vecteur, un facteur et une
fonction. Elle applique ensuite la fonction aux éléments du vecteur
correspondant à un même niveau du facteur. Vite, un exemple~!
<<>>=
tapply(d$age, d$sexe, mean)
@
Qu'est-ce que ça signifie~? Ici \rfunc{tapply} a sélectionné toutes
les observations correspondant à <<~Homme~>>, puis appliqué la
fonction \rfunc{mean} aux valeurs de \texttt{age}
correspondantes. Puis elle a fait de même pour les observations
correspondant à <<~Femme~>>. On a donc ici la moyenne d'âge chez les
hommes et chez les femmes.
On peut fournir à peu près n'importe quelle fonction à \rfunc{tapply}~:
<<>>=
tapply(d$bricol, d$sexe, freq)
@
Les arguments supplémentaires fournis à \rfunc{tapply} sont en fait
fournis directement à la fonction appelée.
<<>>=
tapply(d$bricol, d$sexe, freq, total=TRUE)
@
À noter également, la fonction \rfunc{by} est un équivalent (pour les tableaux
de données) de \rfunc{tapply}. La présentation des résultats diffère
légèrement.
<<>>=
tapply(d$age, d$sexe, mean)
by(d$age, d$sexe, mean)
@
\section{Recodages}
\label{sec_recodages}
Le recodage de variables est une opération extrêmement fréquente lors
du traitement d'enquête. Celui-ci utilise soit l'une des formes
d'indexation décrites précédemment, soit des fonctions \textit{ad hoc}
de \R.
On passe ici en revue différents types de recodage parmi les plus
courants. Les exemples s'appuient, comme précédemment, sur l'extrait
de l'enquête \textit{Histoire de vie}~:
<<>>=
data(hdv2003)
d <- hdv2003
@
\subsection{Convertir une variable}
Il peut arriver qu'on veuille transformer une variable d'un type dans
un autre.
Par exemple, on peut considérer que la variable numérique
\texttt{freres.soeurs} est une <<~fausse~>> variable numérique et
qu'une représentation sous forme de facteur serait plus adéquate. Dans
ce cas il suffit de faire appel à la fonction \rfunc{factor}~:
<<>>=
d$fs.fac <- factor(d$freres.soeurs)
levels(d$fs.fac)
@
La conversion d'une variable caractères en facteur se fait de la même
manière.
La conversion d'un facteur ou d'une variable numérique en variable
caractères peut se faire à l'aide de la fonction \rfunc{as.character}~:
<<>>=
d$fs.char <- as.character(d$freres.soeurs)
d$qualif.char <- as.character(d$qualif)
@
La conversion d'un facteur en caractères est fréquemment utilisé lors des
recodages du fait qu'il est impossible d'ajouter de nouvelles modalités à un
facteur de cette manière. Par exemple, la première des commandes suivantes
génère un message d'avertissement, tandis que les deux autres fonctionnent~:
<<eval=FALSE>>=
d$qualif[d$qualif=="Ouvrier specialise"] <- "Ouvrier"
d$qualif.char <- as.character(d$qualif)
d$qualif.char[d$qualif.char=="Ouvrier specialise"] <- "Ouvrier"
@
Dans le premier cas, le message d'avertissement indique que toutes les
modalités <<~Ouvrier specialise~>> de notre variable
\texttt{qualif} ont été remplacées par des valeurs manquantes \texttt{NA}.
Enfin, une variable de type caractères dont les valeurs seraient des
nombres peut être convertie en variable numérique avec la fonction
\rfunc{as.numeric}. Si on souhaite convertir un facteur en variable
numérique, il faut d'abord le convertir en variable de classe
caractère~:
<<>>=
d$fs.num <- as.numeric(as.character(d$fs.fac))
@
\subsection{Découper une variable numérique en classes}
Le premier type de recodage consiste à découper une variable de type
numérique en un certain nombre de classes. On utilise pour cela la
fonction \rfunc{cut}.
Celle-ci prend, outre la variable à découper, un certain nombre d'arguments~:
\begin{itemize}
\item \texttt{breaks} indique soit le nombre de classes souhaité,
soit, si on lui fournit un vecteur, les limites des classes~;
\item \texttt{labels} permet de modifier les noms de modalités
attribués aux classes~;
\item \texttt{include.lowest} et \texttt{right} influent sur la
manière dont les valeurs situées à la frontière des classes seront
inclues ou exclues~;
\item \texttt{dig.lab} indique le nombre de chiffres après la virgule
à conserver dans les noms de modalités.
\end{itemize}
Prenons tout de suite un exemple et tentons de découper notre variable
\texttt{age} en cinq classes et de placer le résultat dans une
nouvelle variable nommée \texttt{age5cl}~:
<<>>=
d$age5cl <- cut(d$age, 5)
table(d$age5cl)
@
Par défaut \R nous a bien créé cinq classes d'amplitudes égales. La
première classe va de 16,9 à 32,2 ans (en fait de 17 à 32), etc.
Les frontières de classe seraient plus présentables si elles
utilisaient des nombres entiers. On va donc spécifier manuellement le
découpage souhaité, par tranches de 20 ans~:
<<>>=
d$age20 <- cut(d$age, c(0,20,40,60,80,100))
table(d$age20)
@
On aurait pu tenir compte des âges extrêmes pour la première et la
dernière valeur~:
<<>>=
range(d$age)
d$age20 <- cut(d$age, c(17,20,40,60,80,93))
table(d$age20)
@
Les symboles dans les noms attribués aux classes ont leur importance~:
\texttt{(} signifie que la frontière de la classe est exclue, tandis
que \texttt{[} signifie qu'elle est incluse. Ainsi, \texttt{(20,40]}
signifie <<~strictement supérieur à 20 et inférieur ou égal à 40~>>.
On remarque que du coup, dans notre exemple précédent, la valeur
minimale, 17, est exclue de notre première classe, et qu'une
observation est donc absente de ce découpage. Pour résoudre ce
problème on peut soit faire commencer la première classe à 16, soit
utiliser l'option \texttt{include.lowest=TRUE}~:
<<>>=
d$age20 <- cut(d$age, c(16,20,40,60,80,93))
table(d$age20)
d$age20 <- cut(d$age, c(17,20,40,60,80,93), include.lowest=TRUE)
table(d$age20)
@
On peut également modifier le sens des intervalles avec l'option
\texttt{right=FALSE}, et indiquer manuellement les noms des modalités
avec \texttt{labels}~:
<<>>=
d$age20 <- cut(d$age, c(16,20,40,60,80,93), right=FALSE, include.lowest=TRUE)
table(d$age20)
d$age20 <- cut(d$age, c(17,20,40,60,80,93), include.lowest=TRUE, labels=c("<20ans", "21-40 ans", "41-60ans", "61-80ans", ">80ans"))
table(d$age20)
@
\subsubsection{Interface interactive}
\questionr \marqr propose une interface interactive à la fonction
\texttt{cut}, nommée \rfunc{icut}. Elle s'utilise soit dans RStudio via le menu \textit{Addins}, puis \textit{Variable cutting}, soit depuis la console ou un script de la manière suivante~:
<<launchicut,eval=FALSE>>=
icut(d$age)
@
\R devrait alors afficher une interface
semblable à celle de la figure~\ref{fig_interface_icut}, \vpageref{fig_interface_icut}.
\begin{figure}
\begin{center}
\includegraphics[width=0.95\textwidth]{img/interface_icut.png}
\end{center}
\caption{Interface de la commande \texttt{icut}}
\label{fig_interface_icut}
\end{figure}
Vous pouvez alors choisir la variable à découper dans l'onglet \textit{Variable et paramètres}, indiquer les limites de vos classes ainsi que quelques
options complémentaires dans l'onglet \textit{Découpage en classes}, et vérifier le
résultat dans l'onglet \textit{Code et résultat}. Une fois le résultat satisfaisant,
cliquez sur \textit{Done} : si vous êtes sous RStudio le code généré sera directement inséré dans votre script actuel à l'emplacement du curseur. Sinon, ce code sera affiché dans la console et vous pourrez le copier/coller pour l'inclure dans votre script\footnotemark.
\footnotetext{Le fonctionnement des interfaces interactives de \questionr est
décrit plus en détail section~\ref{sec_interfaces}, \vpageref{sec_interfaces}.}
\subsubsection{\textsf{quant.cut}}
Enfin, l'extension \questionr \marqr propose une fonction
\rfunc{quant.cut} permettant de découper une variable numérique en un
nombre de classes donné ayant des efffectifs semblables. Il suffit de
lui passer le nombre de classes en argument~:
<<>>=
d$age6cl <- quant.cut(d$age, 6)
table(d$age6cl)
@
\rfunc{quant.cut} admet les mêmes autres options que \rfunc{cut}
(\texttt{include.lowest, right, labels}\ldots).
\subsection{Regrouper les modalités d'une variable}
Pour regrouper les modalités d'une variable qualitative (d'un facteur
le plus souvent), on peut utiliser directement l'indexation.
Ainsi, si on veut recoder la variable \texttt{qualif} dans une
variable \texttt{qualif.reg} plus <<~compacte~>>, on peut utiliser~:
<<>>=
table(d$qualif)
d$qualif.reg[d$qualif=="Ouvrier specialise"] <- "Ouvrier"
d$qualif.reg[d$qualif=="Ouvrier qualifie"] <- "Ouvrier"
d$qualif.reg[d$qualif=="Employe"] <- "Employe"
d$qualif.reg[d$qualif=="Profession intermediaire"] <- "Intermediaire"
d$qualif.reg[d$qualif=="Technicien"] <- "Intermediaire"
d$qualif.reg[d$qualif=="Cadre"] <- "Cadre"
d$qualif.reg[d$qualif=="Autre"] <- "Autre"
table(d$qualif.reg)
@
On aurait pu représenter ce recodage de manière plus compacte,
notamment en commençant par copier le contenu de \texttt{qualif} dans
\texttt{qualif.reg}, ce qui permet de ne pas s'occuper de ce qui ne
change pas. Il est cependant nécessaire de ne pas copier
\texttt{qualif} sous forme de facteur, sinon on ne pourrait ajouter de
nouvelles modalités. On copie donc la version \textit{caractères} de
\texttt{qualif} grâce à la fonction \rfunc{as.character}~:
<<>>=
d$qualif.reg <- as.character(d$qualif)
d$qualif.reg[d$qualif=="Ouvrier specialise"] <- "Ouvrier"
d$qualif.reg[d$qualif=="Ouvrier qualifie"] <- "Ouvrier"
d$qualif.reg[d$qualif=="Profession intermediaire"] <- "Intermediaire"
d$qualif.reg[d$qualif=="Technicien"] <- "Intermediaire"
table(d$qualif.reg)
@
On peut faire une version encore plus compacte en utilisant
l'opérateur logique \textit{ou} (\rfunc{|})~:
<<>>=
d$qualif.reg <- as.character(d$qualif)
d$qualif.reg[d$qualif=="Ouvrier specialise" | d$qualif=="Ouvrier qualifie"] <- "Ouvrier"
d$qualif.reg[d$qualif=="Profession intermediaire" | d$qualif=="Technicien"] <- "Intermediaire"
table(d$qualif.reg)
@
Enfin, pour terminer ce petit tour d'horizon, on peut également
remplacer l'opérateur \rfunc{|} par \rfunc{\%in\%}, qui peut parfois
être plus lisible~:
<<>>=
d$qualif.reg <- as.character(d$qualif)
d$qualif.reg[d$qualif %in% c("Ouvrier specialise", "Ouvrier qualifie")] <- "Ouvrier"
d$qualif.reg[d$qualif %in% c("Profession intermediaire", "Technicien")] <- "Intermediaire"
table(d$qualif.reg)
@
Dans tous les cas le résultat obtenu est une variable de type
\textit{caractère}. On pourra la convertir en \textit{facteur} par un
simple~:
<<>>=
d$qualif.reg <- factor(d$qualif.reg)
@
Si on souhaite recoder les valeurs manquantes, il suffit de faire
appel à la fonction \rfunc{is.na}~:
<<>>=
table(d$trav.satisf)
d$trav.satisf.reg <- as.character(d$trav.satisf)
d$trav.satisf.reg[is.na(d$trav.satisf)] <- "Valeur manquante"
table(d$trav.satisf.reg)
@
\subsubsection{Interface interactive}
\questionr \marqr propose une interface interactive pour le recodage d'une
variable qualitative (renommage et regroupement de modalités). Cette fonction,
nommée \rfunc{irec}, s'utilise depuis RStudio via le menu \textit{Addins}, puis \textit{Levels recoding}, soit depuis la console de la manière suivante~:
<<launchirec,eval=FALSE>>=
irec(d$qualif)
@
Dans les deux cas, une interface semblable à celle de la figure~\ref{fig_interface_irec}, \vpageref{fig_interface_irec} devrait s'afficher soit directement dans RStudio, soit dans votre navigateur Web.
Vous pouvez alors sélectionner différentes options, et pour chaque ancienne
modalité, indiquer la nouvelle valeur correspondante. Pour regrouper des
modalités, il suffit de leur assigner des nouvelles valeurs identiques. Dans
tous les cas n'hésitez pas à expérimenter, l'interface se contente de générer
du code R mais ne l'exécute pas, et ne
modifie donc jamais vos données~!\footnotemark
\footnotetext{Le fonctionnement des interfaces interactives de \questionr est
décrit plus en détail section~\ref{sec_interfaces}, \vpageref{sec_interfaces}.}
\subsection{Variables calculées}
La création d'une variable numérique à partir de calculs sur une ou
plusieurs autres variables numériques se fait très simplement.
Supposons que l'on souhaite calculer une variable indiquant l'écart
entre le nombre d'heures passées à regarder la télévision et
la moyenne globale de cette variable. On pourrait alors faire~:
<<>>=
range(d$heures.tv, na.rm=TRUE)
mean(d$heures.tv, na.rm=TRUE)
d$ecart.heures.tv <- d$heures.tv - mean(d$heures.tv, na.rm=TRUE)
range(d$ecart.heures.tv, na.rm=TRUE)
mean(d$ecart.heures.tv, na.rm=TRUE)
@
Autre exemple tiré du jeu de données \texttt{rp99}~: si on souhaite
calculer le pourcentage d'actifs dans chaque commune, on peut diviser
la population active \texttt{pop.act} par la population totale
\texttt{pop.tot}.
<<>>=
rp99$part.actifs <- rp99$pop.act / rp99$pop.tot * 100
@
\subsection{Combiner plusieurs variables}
La combinaison de plusieurs variables se fait à l'aide des techniques
d'indexation déjà décrites précédemment. Le plus compliqué est
d'arriver à formuler des conditions parfois complexes de manière rigoureuse.
On peut ainsi vouloir combiner plusieurs variables qualitatives en une seule~:
<<>>=
d$act.manuelles <- NA
d$act.manuelles[d$cuisine=="Oui" & d$bricol=="Oui"] <- "Cuisine et Bricolage"
d$act.manuelles[d$cuisine=="Oui" & d$bricol=="Non"] <- "Cuisine seulement"
d$act.manuelles[d$cuisine=="Non" & d$bricol=="Oui"] <- "Bricolage seulement"
d$act.manuelles[d$cuisine=="Non" & d$bricol=="Non"] <- "Ni cuisine ni bricolage"
table(d$act.manuelles)
@
On peut également combiner variables qualitatives et variables quantitatives~:
<<>>=
d$age.sexe <- NA
d$age.sexe[d$sexe=="Homme" & d$age < 40] <- "Homme moins de 40 ans"
d$age.sexe[d$sexe=="Homme" & d$age >= 40] <- "Homme plus de 40 ans"
d$age.sexe[d$sexe=="Femme" & d$age < 40] <- "Femme moins de 40 ans"
d$age.sexe[d$sexe=="Femme" & d$age >= 40] <- "Femme plus de 40 ans"
table(d$age.sexe)
@
Les combinaisons de variables un peu complexes nécessitent parfois un
petit travail de réflexion. En particulier, l'ordre des commandes de
recodage a parfois une influence dans le résultat final.
\subsection{Variables scores}
Une variable score est une variable calculée en additionnant des poids
accordés aux modalités d'une série de variables qualitatives.
Pour prendre un exemple tout à fait arbitraire, imaginons que nous
souhaitons calculer un score d'activités extérieures. Dans ce score on
considère que le fait d'aller au cinéma <<~pèse~>> 10, celui de pêcher
ou chasser vaut 30 et celui de faire du sport vaut 20. On pourrait
alors calculer notre score de la manière suivante~:
<<>>=
d$score.ext <- 0
d$score.ext[d$cinema=="Oui"] <- d$score.ext[d$cinema=="Oui"] + 10
d$score.ext[d$peche.chasse=="Oui"] <- d$score.ext[d$peche.chasse=="Oui"] + 30
d$score.ext[d$sport=="Oui"] <- d$score.ext[d$sport=="Oui"] + 20
table(d$score.ext)
@
Cette notation étant un peu lourde, on peut l'alléger un peu en
utilisant la fonction \rfunc{ifelse}. Celle-ci prend en argument une
condition et deux valeurs. Si la condition est vraie elle retourne la
première valeur, sinon elle retourne la seconde.
<<>>=
d$score.ext <- 0
d$score.ext <- ifelse(d$cinema=="Oui", 10, 0) +
ifelse(d$peche.chasse=="Oui", 30, 0) +
ifelse(d$sport=="Oui", 20, 0)
table(d$score.ext)
@
\subsection{Vérification des recodages}
Il est très important de vérifier, notamment après les recodages les
plus complexes, qu'on a bien obtenu le résultat escompté. Les deux
points les plus sensibles étant les valeurs manquantes et les erreurs
dans les conditions.
Pour vérifier tout cela le plus simple est sans doute de faire des
tableaux croisés entre la variable recodée et celles ayant servi au
recodage, à l'aide de la fonction \rfunc{table}, et de vérifier le
nombre de valeurs manquantes dans la variable recodée avec
\rfunc{summary}, \rfunc{freq} ou \rfunc{table}.
Par exemple~:
<<>>=
d$act.manuelles <- NA
d$act.manuelles[d$cuisine=="Oui" & d$bricol=="Oui"] <- "Cuisine et Bricolage"
d$act.manuelles[d$cuisine=="Oui" & d$bricol=="Non"] <- "Cuisine seulement"
d$act.manuelles[d$cuisine=="Non" & d$bricol=="Oui"] <- "Bricolage seulement"
d$act.manuelles[d$cuisine=="Non" & d$bricol=="Non"] <- "Ni cuisine ni bricolage"
table(d$act.manuelles, d$cuisine)
table(d$act.manuelles, d$bricol)
@
\section{Tri de tables}
On a déjà évoqué l'existence de la fonction \rfunc{sort}, qui permet
de trier les éléments d'un vecteur.
<<>>=
sort(c(2,5,6,1,8))
@
On peut appliquer cette fonction à une variable, mais celle-ci ne
permet que d'ordonner les valeurs de cette variable, et pas l'ensemble
du tableau de données dont elle fait partie. Pour cela nous avons
besoin d'une autre fonction, nommée \rfunc{order}. Celle-ci ne
renvoie pas les valeurs du vecteur triées, mais les emplacements de
ces valeurs.
Un exemple pour comprendre~:
<<>>=
order(c(15,20,10))
@
Le résultat renvoyé signifie que la plus petite valeur est la valeur
située en 3ème position, suivie de celle en 1ère position et de celle
en 2ème position. Tout cela ne paraît pas passionnant à première vue,
mais si on mélange ce résultat avec un peu d'indexation directe, ça
devient intéressant\ldots
<<>>=
order(d$age)
@
Ce que cette fonction renvoie, c'est l'ordre dans lequel on doit
placer les éléments de \texttt{age}, et donc par extension les lignes
de \texttt{d}, pour que la variable soit triée par ordre
croissant. Par conséquent, si on fait~:
<<>>=
d.tri <- d[order(d$age),]
@
Alors on a trié les lignes de \texttt{d} par ordre d'âge croissant~!
Et si on fait un petit~:
<<>>=
head(d.tri, 3)
@
On a les caractéristiques des trois enquêtés les plus jeunes.
On peut évidemment trier par ordre décroissant en utilisant l'option
\texttt{decreasing=TRUE}. On peut donc afficher les caractéristiques
des trois individus les plus âgés avec~:
<<eval=FALSE>>=
head(d[order(d$age, decreasing=TRUE),], 3)
@
\section{Fusion de tables}
\label{sec_merge}
Lorsqu'on traite de grosses enquêtes, notamment les enquêtes de
l'INSEE, on a souvent à gérer des données réparties dans plusieurs
tables, soit du fait de la construction du questionnaire, soit du fait
de contraintes techniques (fichiers \texttt{dbf} ou \textsf{Excel}
limités à 256 colonnes, par exemple).
Une opération relativement courante consiste à \textit{fusionner}
plusieurs tables pour regrouper tout ou partie des données dans un
unique tableau.
Nous allons simuler artificiellement une telle situation en créant deux
tables à partir de l'extrait de l'enquête \textit{Histoire de vie}~:
<<>>=
data(hdv2003)
d <- hdv2003
dim(d)
d1 <- subset(d, select=c("id","age","sexe"))
dim(d1)
d2 <- subset(d, select=c("id","clso"))
dim(d2)
@
On a donc deux tableaux de données, \texttt{d1} et \texttt{d2},
comportant chacun 2000 lignes et respectivement 3 et 2
colonnes. Comment les rassembler pour n'en former qu'un~?
Intuitivement, cela paraît simple. Il suffit de <<~coller~>>
\texttt{d2} à la droite de \texttt{d1}, comme dans l'exemple suivant.
\begin{center}
\begin{tabular}{ccccc}
\begin{tabular}{r|r|r}
\textsf{Id} & \textsf{V1} & \textsf{V2} \\
\hline
1 & H & 12 \\
2 & H & 17 \\
3 & F & 41 \\
4 & F & 9 \\
\vdots & \vdots & \vdots \\
\end{tabular}
&
\huge{+}
&
\begin{tabular}{r|r}
\textsf{Id} & \textsf{V3} \\
\hline
1 & Rouge \\
2 & Bleu \\
3 & Bleu\\
4 & Rouge \\
\vdots & \vdots \\
\end{tabular}
&
\huge{=}
&
\begin{tabular}{r|r|r|r}
\textsf{Id} & \textsf{V1} & \textsf{V2} & \textsf{V3}\\
\hline
1 & H & 12 & Rouge\\
2 & H & 17 & Bleu \\
3 & F & 41 & Bleu\\
4 & F & 9 & Rouge \\
\vdots & \vdots & \vdots & \vdots \\
\end{tabular}
\\
\end{tabular}
\end{center}
Cela semble fonctionner. La fonction qui permet d'effectuer cette
opération sous \R s'appelle \rfunc{cbind}, elle <<~colle~>> des
tableaux côte à côte en regroupant leurs
colonnes\footnote{L'équivalent de \rfunc{cbind} pour les lignes
s'appelle \rfunc{rbind}.}.
<<>>=
cbind(d1,d2)
@
À part le fait qu'on a une colonne \texttt{id} en double, le résultat
semble satisfaisant. À première vue seulement. Imaginons maintenant
que nous avons travaillé sur \texttt{d1} et \texttt{d2}, et que nous
avons ordonné les lignes de \texttt{d1} selon l'âge des enquêtés~:
<<>>=
d1 <- d1[order(d1$age),]
@
Répétons l'opération de collage~:
<<>>=
cbind(d1,d2)
@
Que constate-t-on~? La présence de la variable \texttt{id} en double
nous permet de voir que les identifiants ne coïncident plus~! En
regroupant nos colonnes nous avons donc attribué à des individus les
réponses d'autres individus.
La commande \rfunc{cbind} ne peut en effet fonctionner que si les deux
tableaux ont exactement le même nombre de lignes, et dans le même
ordre, ce qui n'est pas le cas ici.
On va donc être obligé de pocéder à une \textit{fusion} des deux
tableaux, qui va permettre de rendre à chaque ligne ce qui lui
appartient. Pour cela nous avons besoin d'un identifiant qui permet
d'identifier chaque ligne de manière unique et qui doit être présent
dans tous les tableaux. Dans notre cas, c'est plutôt rapide, il s'agit
de la variable \texttt{id}.
Une fois l'identifiant identifié\footnote{Si vous me passez
l'expression\ldots}, on peut utiliser la commande
\rfunc{merge}. Celle-ci va fusionner les deux tableaux en supprimant
les colonnes en double et en regroupant les lignes selon leurs identifiants~:
<<dcomplet>>=
d.complet <- merge(d1,d2, by="id")
head(d.complet)
@
Ici l'utilisation de la fonction est plutôt simple car nous sommes
dans le cas de figure idéal~: les lignes correspondent parfaitement et
l'identifiant est clairement identifié. Parfois les choses peuvent
être un peu plus compliquées~:
\begin{itemize}
\item parfois les identifiants n'ont pas le même nom dans les deux
tableaux. On peut alors les spécifier par les options \texttt{by.x}
et \texttt{by.y}~;
\item parfois les deux tableaux comportent des colonnes (hors
identifiants) ayant le même nom. \rfunc{merge} conserve dans ce
cas ces deux colonnes mais les renomme en les suffixant par
\texttt{.x} pour celles provenant du premier tableau, et \texttt{.y}
pour celles du second~;
\item parfois on n'a pas d'identifiant unique préétabli, mais on en
construit un à partir de plusieurs variables. On peut alors donner
un vecteur en paramètres de l'option \texttt{by}, par exemple
\texttt{by=c("nom","prenom","date.naissance")}.
\end{itemize}
Une subtilité supplémentaire intervient lorsque les deux tableaux
fusionnés n'ont pas exactement les mêmes lignes. Par défaut,
\rfunc{merge} ne conserve que les lignes présentes dans les deux tableaux~:
\begin{center}
\begin{tabular}{ccccc}
\begin{tabular}{r|r}
\textsf{Id} & \textsf{V1} \\
\hline
1 & H \\
2 & H \\
3 & F \\
\end{tabular}
&
\huge{+}
&
\begin{tabular}{r|r}
\textsf{Id} & \textsf{V2} \\
\hline
1 & 10 \\
2 & 15 \\
5 & 31 \\
\end{tabular}
&
\huge{=}
&
\begin{tabular}{r|r|r}
\textsf{Id} & \textsf{V1} & \textsf{V2} \\
\hline
1 & H & 10\\
2 & H & 15\\
\end{tabular}
\\
\end{tabular}
\end{center}
On peut cependant modifier ce comportement avec les options
\texttt{all.x=TRUE} et \texttt{all.y=TRUE}. La première option indique
de conserver toutes les lignes du premier tableau. Dans ce cas
\rfunc{merge} donne une valeur \texttt{NA} pour ces lignes aux
colonnes provenant du second tableau. Ce qui donnerait~:
\begin{center}
\begin{tabular}{ccccc}
\begin{tabular}{r|r}
\textsf{Id} & \textsf{V1} \\
\hline
1 & H \\
2 & H \\
3 & F \\
\end{tabular}
&
\huge{+}
&
\begin{tabular}{r|r}
\textsf{Id} & \textsf{V2} \\
\hline
1 & 10 \\
2 & 15 \\
5 & 31 \\
\end{tabular}
&
\huge{=}
&
\begin{tabular}{r|r|r}
\textsf{Id} & \textsf{V1} & \textsf{V2} \\
\hline
1 & H & 10\\
2 & H & 15\\
3 & F & NA\\
\end{tabular}
\\
\end{tabular}
\end{center}
\texttt{all.y} fait la même chose en conservant toutes les lignes du
second tableau. On peut enfin décider toutes les lignes des deux
tableaux en utilisant à la fois \texttt{all.x=TRUE} et
\texttt{all.y=TRUE}, ce qui donne~:
\begin{center}
\begin{tabular}{ccccc}
\begin{tabular}{r|r}
\textsf{Id} & \textsf{V1} \\
\hline
1 & H \\
2 & H \\
3 & F \\
\end{tabular}
&
\huge{+}
&
\begin{tabular}{r|r}
\textsf{Id} & \textsf{V2} \\
\hline
1 & 10 \\
2 & 15 \\
5 & 31 \\
\end{tabular}
&
\huge{=}
&
\begin{tabular}{r|r|r}
\textsf{Id} & \textsf{V1} & \textsf{V2} \\
\hline
1 & H & 10\\
2 & H & 15\\
3 & F & NA\\
5 & NA & 31 \\
\end{tabular}
\\
\end{tabular}
\end{center}
Parfois, l'un des identifiants est présent à plusieurs reprises dans
l'un des tableaux (par exemple lorsque l'une des tables est un
ensemble de ménages et que l'autre décrit l'ensemble des individus de
ces ménages). Dans ce cas les lignes de l'autre table sont dupliquées
autant de fois que nécessaires~:
\begin{center}
\begin{tabular}{ccccc}
\begin{tabular}{r|r}
\textsf{Id} & \textsf{V1} \\
\hline
1 & H \\
2 & H \\
3 & F \\
\end{tabular}
&
\huge{+}
&
\begin{tabular}{r|r}
\textsf{Id} & \textsf{V2} \\
\hline
1 & 10 \\
1 & 18 \\
1 & 21 \\
2 & 11 \\
3 & 31 \\
\end{tabular}
&
\huge{=}
&
\begin{tabular}{r|r|r}
\textsf{Id} & \textsf{V1} & \textsf{V2} \\
\hline
1 & H & 10\\
1 & H & 18\\
1 & H & 21\\
2 & H & 11\\
3 & F & 31\\
\end{tabular}
\\
\end{tabular}
\end{center}
\section{Organiser ses scripts}
Il ne s'agit pas ici de manipulation de données à proprement parler,
mais plutôt d'une conséquence de ce qui a été vu précédemment~: à
mesure que recodages et traitements divers s'accumulent, votre script
\R risque de devenir rapidement très long et pas très pratique à éditer.
Il est très courant de répartir son travail entre différents fichiers,
ce qui est rendu très simple par la fonction \rfunc{source}. Celle-ci
permet de lire le contenu d'un fichier de script et d'exécuter son
contenu.
Prenons tout de suite un exemple. La plupart des scripts \R commencent
par charger les extensions utiles, importer les données, effectuer
manipulations, traitements et recodages, puis à mettre en oeuvre les
analyses. Prenons le fichier fictif suivant~:
<<orga1,eval=FALSE,prompt=FALSE>>=
library(questionr)
library(foreign)
## IMPORT DES DONNÉES
d1 <- read.dbf("data/tab1.dbf")
d2 <- read.dbf("data/tab2.dbf")
d <- merge(d1, d2, by="id")
## RECODAGES
d$tx.chomage <- as.numeric(d$tx.chomage)
d$pcs[d$pcs == "Ouvrier qualifie"] <- "Ouvrier"
d$pcs[d$pcs == "Ouvrier specialise"] <- "Ouvrier"
d$age5cl <- cut(d$age, 5)
## ANALYSES
tab <- table(d$tx.chomage, d$age5cl)
tab
chisq.test(tab)
@
Une manière d'organiser notre script\footnote{Ceci n'est qu'une
suggestion, la manière d'organiser (ou non) son travail étant bien
évidemment très hautement subjective.} pourrait être de placer les
opérations d'import des données et celles de recodage dans deux
fichiers scripts séparés. Créons alors un fichier nommé
\texttt{import.R} dans notre répertoire de travail et copions les
lignes suivantes~:
<<orga2,eval=FALSE,prompt=FALSE>>=
## IMPORT DES DONNÉES
d1 <- read.dbf("data/tab1.dbf")
d2 <- read.dbf("data/tab2.dbf")
d <- merge(d1, d2, by="id")
@
Créons également un fichier \texttt{recodages.R} avec le contenu suivant~:
<<orga3,eval=FALSE,prompt=FALSE>>=
## RECODAGES
d$tx.chomage <- as.numeric(d$tx.chomage)
d$pcs[d$pcs == "Ouvrier qualifie"] <- "Ouvrier"
d$pcs[d$pcs == "Ouvrier specialise"] <- "Ouvrier"
d$age5cl <- cut(d$age, 5)
@
Dès lors, si nous rajoutons les appels à la fonction \rfunc{source}
qui vont bien, le fichier suivant sera strictement équivalent à notre
fichier de départ~:
<<orga4,eval=FALSE,prompt=FALSE>>=
library(questionr)
library(foreign)
source("import.R")
source("recodages.R")
## ANALYSES
tab <- table(d$tx.chomage, d$age5cl)
tab
chisq.test(tab)
@
Au fur et à mesure du travail sur les données, on placera les
recodages que l'on souhaite conserver dans le fichier
\texttt{recodages.R}.
Cette méthode présente plusieurs avantages~:
\begin{itemize}
\item bien souvent, lorsqu'on effectue des recodages on se retrouve
avec des variables recodées qu'on ne souhaite pas conserver. Si on
prend l'habitude de placer les recodages intéressants dans le
fichier \texttt{recodages.R}, alors il suffit d'exécuter les cinq
premières lignes du fichier pour se retrouver avec un tableau de
données \texttt{d} propre et complet.
\item on peut répartir ses analyses dans différents scripts. Il suffit
alors de copier les cinq premières lignes du fichier précédent dans
chacun des scripts, et on aura l'assurance de travailler sur
exactement les mêmes données.
\end{itemize}
Le premier point illustre l'une des caractéristiques de \R~: il est
rare que l'on stocke les données modifiées. En général on repart
toujours du fichier source original, et les recodages sont conservés
sous forme de scripts et recalculés à chaque fois qu'on recommence à
travailler. Ceci offre une traçabilité parfaite du traitement effectué
sur les données.
\section{Exercices}
\begin{exo}{manip_rename}
Renommer la variable \texttt{clso} du jeu de données
\texttt{hdv2003} en \texttt{classes.sociales}, puis la renommer en
\texttt{clso}.
\end{exo}
\begin{exo}{manip_factor}
Réordonner les niveaux du facteur \texttt{clso} pour que son tri
à plat s'affiche de la manière suivante~:
<<echo=FALSE>>=
tmp <- factor(d$clso, levels=c("Non", "Ne sait pas", "Oui"))
table(tmp)
@
\end{exo}
\begin{exo}{manip_index_direct}
Affichez~:
\begin{itemize}
\item les 3 premiers éléments de la variable \texttt{cinema}
\item les éléments 12 à 30 de la variable \texttt{lecture.bd}
\item les colonnes 4 et 8 des lignes 5 et 12 du jeu de données \texttt{hdv2003}
\item les 4 derniers éléments de la variable \texttt{age}
\end{itemize}
\end{exo}
\begin{exo}{manip_souspop}
Construisez les sous-tableaux suivants avec la fonction \texttt{subset}~:
\begin{itemize}
\item âge et sexe des lecteurs de BD
\item ensemble des personnes n'étant pas chômeur (variable
\texttt{occup}), sans la variable \texttt{cinema}
\item identifiants des personnes de plus de 45 ans écoutant du hard rock
\item femmes entre 25 et 40 ans n'ayant pas fait de sport dans les
douze derniers mois
\item hommes ayant entre 2 et 4 frères et s\oe{}urs et faisant la
cuisine ou du bricolage
\end{itemize}
\end{exo}
\begin{exo}{manip_tapply}
Calculez le nombre moyen d'heures passées devant la télévision chez
les lecteurs de BD, d'abord en construisant les sous-populations,
puis avec la fonction \texttt{tapply}.
\end{exo}
\begin{exo}{manip_convert}
Convertissez la variable \texttt{freres.soeurs} en variable de type
caractères. Convertissez cette nouvelle variable en facteur. Puis
convertissez à nouveau ce facteur en variable numérique. Vérifiez
que votre variable finale est identique à la variable de départ.
\end{exo}
\begin{exo}{manip_decoup}
Découpez la variable \texttt{freres.soeurs}~:
\begin{itemize}
\item en cinq classes d'amplitude égale
\item en catégories <<~de 0 à 2~>>, <<~de 2 à 4~>>, <<~plus de 4~>>, avec les
étiquettes correspondantes
\item en quatre classes d'effectif équivalent
\item d'où vient la différence d'effectifs entre les deux découpages
précédents~?
\end{itemize}
\end{exo}
\begin{exo}{manip_regroup}
Recodez la variable \texttt{trav.imp} en \texttt{trav.imp2cl} pour
obtenir les modalités <<~Le plus ou aussi important~>> et <<~moins
ou peu important~>>. Vérifiez avec des tris à plat et un tableau croisé.
Recodez la variable \texttt{relig} en \texttt{relig.4cl} en
regroupant les modalités <<~Pratiquant regulier~>> et <<~Pratiquant
occasionnel~>> en une seule modalité <<~Pratiquant~>>, et en
remplaçant la modalité <<~NSP ou NVPR~>> par des valeurs
manquantes. Vérifiez avec un tri croisé.
\end{exo}
\begin{exo}{manip_combine}
Créez une variable ayant les modalités suivantes~:
\begin{itemize}
\item Homme de plus de 40 ans lecteur de BD
\item Homme de plus de 30 ans
\item Femme faisant du bricolage
\item Autre
\end{itemize}
Vérifier avec des tris croisés.
\end{exo}
\begin{exo}{manip_tri}
Ordonner le tableau de données selon le nombre de frères et soeurs
croissant. Afficher le sexe des 10 individus regardant le plus la
télévision.
\end{exo}
\chapter{Statistique bivariée}
On entend par statistique bivariée l'étude des relations entre deux
variables, celles-ci pouvant être quantitatives ou qualitatives.
Comme dans la partie précédente, on travaillera sur les jeux de données
fournis avec l'extension \questionr \marqr et tiré de l'enquête
\textit{Histoire de vie} et du recensement 1999~:
<<>>=
data(hdv2003)
d <- hdv2003
data(rp99)
@
\section{Deux variables quantitatives}
La comparaison de deux variables quantitatives se fait en premier lieu
graphiquement, en représentant l'ensemble des couples de valeurs. On
peut ainsi représenter les valeurs du nombre d'heures passées devant
la télévision selon l'âge (figure~\ref{fig_tvage} \vpageref{fig_tvage}).
\begin{figure}
<<>>=
plot(d$age, d$heures.tv)
@
\caption{Nombre d'heures de télévision selon l'âge}
\label{fig_tvage}
\end{figure}
Le fait que des points sont superposés ne facilite pas la lecture du
graphique. On peut utiliser une représentation avec des points
semi-transparents (figure~\ref{fig_tvagealpha} \vpageref{fig_tvagealpha}).
\begin{figure}
<<>>=
plot(d$age, d$heures.tv, pch=19, col=rgb(1,0,0,0.1))
@
\caption{Nombre d'heures de télévision selon l'âge avec semi-transparence}
\label{fig_tvagealpha}
\end{figure}
Plus sophistiqué, on peut faire une estimation locale de densité et
représenter le résultat sous forme de <<~carte~>>. Pour cela on
commence par isoler les deux variables, supprimer les observations
ayant au moins une valeur manquante à l'aide de la fonction
\rfunc{complete.cases}, estimer la densité locale à l'aide de la
fonction \rfunc{kde2d} de l'extension
\textsf{MASS}\footnote{\textsf{MASS} est installée par défaut avec la
version de base de \R.} et représenter le tout à l'aide d'une des
fonctions \rfunc{image}, \rfunc{contour} ou
\rfunc{filled.contour}\ldots Le résultat est donné
figure~\ref{fig_filledcontour} \vpageref{fig_filledcontour}.
\begin{figure}
<<filled-contour,fig.keep="last">>=
library(MASS)
tmp <- d[,c("age","heures.tv")]
tmp <- tmp[complete.cases(tmp),]
filled.contour(kde2d(tmp$age,tmp$heures.tv),color=terrain.colors)
@
\caption{Représentation de l'estimation de densité locale}
\label{fig_filledcontour}
\end{figure}
Dans tous les cas, il n'y a pas de structure très nette qui semble se
dégager. On peut tester ceci mathématiquement en calculant le
c\oe{}fficient de corrélation entre les deux variables à l'aide de la
fonction \rfunc{cor}~:
<<>>=
cor(d$age, d$heures.tv, use="complete.obs")
@
L'option \texttt{use} permet d'éliminer les observations pour
lesquelles l'une des deux valeurs est manquante. Le c\oe{}fficient de
corrélation est très faible.
On va donc s'intéresser plutôt à deux variables présentes dans le jeu
de données \texttt{rp99}, la part de diplômés du supérieur et la
proportion de cadres dans les communes du Rhône en 1999.
À nouveau, commençons par représenter les deux variables
(figure~\ref{fig_cadresup} \vpageref{fig_cadresup}). Ça ressemble déjà
beaucoup plus à une relation de type linéaire.
\begin{figure}
<<>>=
plot(rp99$dipl.sup, rp99$cadres, ylab="Part des cadres", xlab="Part des diplomês du supérieur")
@
\caption{Proportion de cadres et proportion de diplômés du supérieur}
\label{fig_cadresup}
\end{figure}
Calculons le coefficient de corrélation~:
<<>>=
cor(rp99$dipl.sup, rp99$cadres)
@
C'est beaucoup plus proche de 1. On peut alors effectuer une
régression linéaire complète en utilisant la fonction \rfunc{lm}~:
<<>>=
reg <- lm(cadres ~ dipl.sup, data=rp99)
summary(reg)
@
Le résultat montre que les c\oe{}fficients sont significativement
différents de 0. La part de cadres augmente donc avec celle de
diplômés du supérieur (ô surprise). On peut très facilement
représenter la droite de régression à l'aide de la fonction
\rfunc{abline} (figure~\ref{fig_regcad} \vpageref{fig_regcad}).
\begin{figure}
<<>>=
plot(rp99$dipl.sup, rp99$cadres, ylab="Part des cadres", xlab="Part des diplômés du supérieur")
abline(reg, col="red")
@
\caption{Régression de la proportion de cadres par celle de diplômés
du supérieur}
\label{fig_regcad}
\end{figure}
\begin{astuce}
On remarquera que le premier argument passé à la fonction \rfunc{lm} a une
syntaxe un peu particulière. Il s'agit d'une \textit{formule}, utilisée de
manière générale dans les modèles statistiques. On indique la variable
d'intérêt à gauche et la variable explicative à droite, les deux étant
séparées par un tilde \~{} (obtenu sous \textsf{Windows} en appuyant
simultanément sur les touches \texttt{<Alt Gr>} et \texttt{<2>}). On
remarquera que les noms des colonnes de notre tableau de données ont été
écrites sans guillemets. Dans le cas présent, nous avons calculé une
régression linéaire simple entre deux variables, d'où l'écriture
\texttt{cadres \~{} dipl.sup}. Si nous avions
voulu expliquer une variable \texttt{z} par deux variables \texttt{x} et
\texttt{y}, nous aurions écrit \texttt{z \~{} x + y}. Il est possible de
spécifier des modèles encore plus complexes. Pour un aperçu de la syntaxe des
formules sous \R, voir
\url{http://ww2.coastal.edu/kingw/statistics/R-tutorials/formulae.html}.
\end{astuce}
\section{Une variable quantitative et une variable qualitative}
Quand on parle de comparaison entre une variable quantitative et une
variable qualitative, on veut en général savoir si la distribution des
valeurs de la variable quantitative est la même selon les modalités de
la variable qualitative. En clair~: est ce que l'âge de ceux qui
écoutent du hard rock est différent de l'âge de ceux qui n'en écoutent
pas~?
Là encore, l'idéal est de commencer par une représentation
graphique. Les boîtes à moustaches sont parfaitement adaptées pour
cela.
Si on a construit des sous-populations d'individus écoutant ou non du
hard rock, on peut utiliser la fonction \rfunc{boxplot} comme indiqué
figure~\ref{fig_boxplotage} \vpageref{fig_boxplotage}.
\begin{figure}
<<>>=
d.hard <- subset(d, hard.rock=="Oui")
d.non.hard <- subset(d, hard.rock=="Non")
boxplot(d.hard$age, d.non.hard$age)
@
\caption{\textit{Boxplot} de la répartition des âges (sous-populations)}
\label{fig_boxplotage}
\end{figure}
Mais construire les sous-populations n'est pas nécessaire. On peut
utiliser directement la version de \rfunc{boxplot} prenant une
\textit{formule} en argument (figure~\ref{fig_boxplotageb}
\vpageref{fig_boxplotageb}).
\begin{figure}
<<>>=
boxplot(age ~ hard.rock, data=d)
@
\caption{\textit{Boxplot} de la répartition des âges (formule)}
\label{fig_boxplotageb}
\end{figure}
À première vue, ô surprise, la population écoutant du hard rock a
l'air sensiblement plus jeune. Peut-on le tester mathématiquement~? On
peut calculer la moyenne d'âge des deux groupes en utilisant la
fonction \rfunc{tapply}\footnote{Fonction décrite
\vpageref{sec_tapply}.}~:
<<>>=
tapply(d$age, d$hard.rock, mean)
@
L'écart est très important. Est-il statistiquement significatif~? Pour
cela on peut faire un test \textit{t} de comparaison de moyennes à
l'aide de la fonction \rfunc{t.test}~:
<<>>=
t.test(d$age ~ d$hard.rock)
@
Le test est extrêmement significatif. L'intervalle de confiance à
95~\% de la différence entre les deux moyennes va de 14,5 ans à 21,8 ans.
\begin{important}
La valeur affichée pour \textit{p} est de \texttt{1.611e-07}. Cette valeur
peut paraître étrange pour les non avertis. Cela signifie tout simplement
1,611 multiplié par 10 à la puissance -7, autrement dit 0,0000001611. Cette
manière de représenter un nombre est couramment appelée \textit{notation
scientifique}.
\end{important}
Nous sommes cependant allés un peu vite en besogne, car nous avons
négligé une hypothèse fondamentale du test \textit{t}~: les ensembles
de valeur comparés doivent suivre approximativement une loi normale et
être de même variance\footnote{Concernant cette seconde condition, \R
propose une option nommée \texttt{var.equal} qui permet d'utiliser
une approximation dans le cas où les variances ne sont pas
égales}. Comment le vérifier~?
D'abord avec un petit graphique, comme sur la
figure~\ref{fig_histnorm} \vpageref{fig_histnorm}.
\begin{figure}
<<fig.width=10>>=
par(mfrow=c(1,2))
hist(d$age[d$hard.rock=="Oui"], main="Hard rock", col="red")
hist(d$age[d$hard.rock=="Non"], main="Sans hard rock", col="red")
@
\caption{Distribution des âges pour appréciation de la normalité}
\label{fig_histnorm}
\end{figure}
Ça a l'air à peu près bon pour les <<~Sans hard rock~>>, mais un peu
plus limite pour les fans de \textit{Metallica}, dont les effectifs
sont d'ailleurs assez faibles. Si on veut en avoir le c\oe{}ur net on
peut utiliser le test de normalité de Shapiro-Wilk avec la fonction
\rfunc{shapiro.test}~:
<<>>=
shapiro.test(d$age[d$hard.rock=="Oui"])
shapiro.test(d$age[d$hard.rock=="Non"])
@
Visiblement, le test estime que les distributions ne sont pas
suffisamment proches de la normalité dans les deux cas.
Et concernant l'égalité des variances~?
<<>>=
tapply(d$age, d$hard.rock, var)
@
L'écart n'a pas l'air négligeable. On peut le vérifier avec le test
fourni par la fonction \rfunc{var.test}~:
<<>>=
var.test(d$age ~ d$hard.rock)
@
La différence est très significative. En toute rigueur le test
\textit{t} n'aurait donc pas pu être utilisé.
\textit{Damned~!} Ces maudits tests statistiques vont-ils nous
empêcher de faire connaître au monde entier notre fabuleuse découverte
sur l'âge des fans de \textit{Sepultura}~? Non~! Car voici qu'approche
à l'horizon un nouveau test, connu sous le nom de
\textit{Wilcoxon/Mann-Whitney}. Celui-ci a l'avantage d'être
\textit{non-paramétrique}, c'est à dire de ne faire aucune hypothèse
sur la distribution des échantillons comparés. Par contre il ne
compare pas des différences de moyennes mais des différences de
médianes~:
<<>>=
wilcox.test(d$age ~ d$hard.rock)
@
Ouf~! La différence est hautement significative\footnote{Ce test peut
également fournir un intervalle de confiance avec l'option
\texttt{conf.int=TRUE}.}. Nous allons donc pouvoir entamer la
rédaction de notre article pour la \textit{Revue française de
sociologie}.
\section{Deux variables qualitatives}
La comparaison de deux variables qualitatives s'appelle en général un
\textit{tableau croisé}. C'est sans doute l'une des analyses les plus
fréquentes lors du traitement d'enquêtes en sciences sociales.
\subsection{Tableau croisé}
La manière la plus simple d'obtenir un tableau croisé est d'utiliser
la fonction \rfunc{table} en lui donnant en paramètres les deux
variables à croiser. En l'occurrence nous allons croiser un recodage
du niveau de qualification regroupé avec le fait de pratiquer un
sport.
On commence par calculer la variable recodée et par afficher le tri à
plat des deux variables~:
<<>>=
d$qualreg <- as.character(d$qualif)
d$qualreg[d$qualif %in% c("Ouvrier specialise", "Ouvrier qualifie")] <- "Ouvrier"
d$qualreg[d$qualif %in% c("Profession intermediaire", "Technicien")] <- "Intermediaire"
table(d$qualreg)
table(d$sport)
@
Le tableau croisé des deux variables s'obtient de la manière
suivante~:
<<>>=
table(d$sport, d$qualreg)
@
Il est d'ailleurs tout à fait possible de croiser trois variables ou plus. Par
exemple~:
<<>>=
table(d$sport,d$cuisine,d$sexe)
@
On n'a cependant que les effectifs, ce qui rend difficile les
comparaisons. L'extension \questionr \marqr fournit des fonctions
permettant de calculer les pourcentages lignes, colonnes et totaux
d'un tableau croisé.
Les pourcentages lignes s'obtiennent avec la fonction
\rfunc{lprop}. Celle-ci s'applique au tableau croisé généré par
\rfunc{table}~:
<<>>=
tab <- table(d$sport, d$qualreg)
lprop(tab)
@
Les pourcentages ligne ne nous intéressent guère ici. On ne cherche
pas à voir quelle est la proportion de cadres parmi ceux qui pratiquent
un sport, mais plutôt quelle est la proportion de sportifs chez les
cadres. Il nous faut donc des pourcentages colonnes, que l'on obtient
avec la fonction \rfunc{cprop}~:
<<>>=
cprop(tab)
@
Dans l'ensemble, le pourcentage de personnes ayant pratiqué un sport
est de 35,6~\%. Mais cette proportion varie fortement d'une catégorie
professionnelle à l'autre~: 55,0~\% chez les cadres contre 23,0~\%
chez les ouvriers.
À noter qu'on peut personnaliser l'affichage de ces tableaux de
pourcentages à l'aide de différentes options, dont \texttt{digits},
qui règle le nombre de décimales à afficher, et \texttt{percent}, qui
indique si on souhaite ou non rajouter un symbole \% dans chaque case
du tableau. Cette personnalisation peut se faire directement au moment
de la génération du tableau, et dans ce cas elle sera utilisée par défaut~:
<<>>=
ctab <- cprop(tab, digits=2, percent=TRUE)
ctab
@
Ou bien ponctuellement en passant les mêmes arguments aux fonctions
\rfunc{print} (pour affichage dans \R) ou \rfunc{clipcopy} (pour export
vers un logiciel externe)~:
<<>>=
ctab <- cprop(tab)
print(ctab, percent=TRUE)
@
\subsection{\texorpdfstring{$\chi^2$}{X\texttwosuperior} et dérivés}
Pour tester l'existence d'un lien entre les modalités des deux
variables, on va utiliser le très classique test du
$\chi^2$\footnote{On ne donnera pas plus d'indications sur le test du
$\chi^2$ ici. Les personnes désirant une présentation plus détaillée
pourront se reporter (attention, séance d'autopromotion~!) à la page
suivante~:
\url{http://alea.fr.eu.org/pages/khi2}.}. Celui-ci
s'obtient grâce à la fonction \rfunc{chisq.test}, appliquée au
tableau croisé obtenu avec \rfunc{table}\footnote{On peut aussi
appliquer directement le test en spécifiant les deux variables à
croiser \textit{via} \texttt{chisq.test(d\$qualreg, d\$sport)}}~:
<<>>=
chisq.test(tab)
@
Le test est hautement significatif, on ne peut pas considérer qu'il y
a indépendance entre les lignes et les colonnes du tableau.
On peut affiner l'interprétation du test en déterminant dans quelle
case l'écart à l'indépendance est le plus significatif en utilisant
les \textit{résidus} du test. Ceux-ci sont notamment affichables avec
la fonction \rfunc{chisq.residuals} \marqr de \questionr~:
<<>>=
chisq.residuals(tab)
@
Les cases pour lesquelles l'écart à l'indépendance est significatif
ont un résidu dont la valeur est supérieure à 2 ou inférieure à
-2. Ici on constate que la pratique d'un sport est sur-représentée
parmi les cadres et, à un niveau un peu moindre, parmi les professions
intermédiaires, tandis qu'elle est sous-représentée chez les ouvriers.
Enfin, on peut calculer le c\oe{}fficient de contingence de Cramer du
tableau, qui peut nous permettre de le comparer par la suite à
d'autres tableaux croisés. On peut pour cela utiliser la fonction
\rfunc{cramer.v}\marqr de \questionr~:
<<>>=
cramer.v(tab)
@
Et pour un tableau à $2 \times 2$ entrées, il est possible de calculer le test exact de
Fisher avec la fonction \rfunc{fisher.test}. On peut soit lui passer le
résultat de \rfunc{table}, soit directement les deux variables à croiser.
<<>>=
lprop(table(d$sexe,d$cuisine))
fisher.test(table(d$sexe,d$cuisine))
@
\subsection{Représentation graphique}
Enfin, on peut obtenir une représentation graphique synthétisant
l'ensemble des résultats obtenus sous la forme d'un graphique en
mosaïque, grâce à la fonction \rfunc{mosaicplot}. Le résultat est
indiqué figure~\ref{fig_mosaicplot} \vpageref{fig_mosaicplot}.
\begin{figure}
<<>>=
mosaicplot(qualreg ~ sport, data=d, shade=TRUE, main="Graphe en mosaïque")
@
\caption{Exemple de graphe en mosaïque}
\label{fig_mosaicplot}
\end{figure}
Comment interpréter ce graphique haut en couleurs\footnote{Sauf s'il
est imprimé en noir et blanc\ldots}~? Chaque rectangle
représente une case de tableau. Sa largeur correspond au pourcentage
des modalités en colonnes (il y'a beaucoup d'employés et d'ouvriers et
très peu d'<<~autres~>>). Sa hauteur correspond aux
pourcentages-colonnes~: la proportion de sportifs chez les cadres est
plus élevée que chez les employés. Enfin, la couleur de la case
correspond au résidu du test du $\chi^2$ correspondant~: les cases en
rouge sont sous-représentées, les cases en bleu sur-représentées, et
les cases blanches sont statistiquement proches de l'hypothèse
d'indépendance.
\begin{figure}
<<>>=
barplot(cprop(tab,total=FALSE),
main="Pratique du sport selon le niveau de qualification")
@
\caption{Exemple de barres cumulées }
\label{fig_barplot_cum}
\end{figure}
Lorsque l'on s'intéresse principalement aux variations d'une variable selon une
autre, par exemple ici à la pratique du sport selon le niveau de qualification,
il peut être intéressant de présenter les pourcentages en colonne sous la forme
de barres cumulées. Voir figure~\ref{fig_barplot_cum} \vpageref{fig_barplot_cum}.
\chapter{Données pondérées}
S'il est tout à fait possible de travailler avec des données pondérées
sous \R, cette fonctionnalité n'est pas aussi bien intégrée que dans
la plupart des autres logiciels de traitement statistique. En
particulier, il y a plusieurs manières possibles de gérer la pondération.
Dans ce qui suit, on utilisera le jeu de données tiré de l'enquête
\textit{Histoire de vie} et notamment sa variable de pondération
\texttt{poids}\footnote{On notera que cette variable est utilisée à
titre purement illustratif. Le jeu de données étant un extrait
d'enquête et la variable de pondération n'ayant pas été recalculée,
elle n'a ici à proprement parler aucun sens.}.
<<>>=
data(hdv2003)
d <- hdv2003
range(d$poids)
@
\section{Options de certaines fonctions}
Tout d'abord, certaines fonctions de \R acceptent en argument un
vecteur permettant de pondérer les observations (l'option est en
général nommée \texttt{weights} ou \texttt{row.w}). C'est le cas par
exemple des méthodes d'estimation de modèles linéaires (\rfunc{lm}) ou
de modèles linéaires généralisés (\rfunc{glm}), ou dans les analyses
de correspondances des extensions \textsf{ade4} (\rfunc{dudi.acm}) ou
\textsf{FactoMineR} (\texttt{MCA}).
Par contre cette option n'est pas présente dans les fonctions de base
comme \rfunc{mean}, \rfunc{var}, \rfunc{table} ou \rfunc{chisq.test}.
\section{Fonctions de l'extension \questionr}
L'extension \questionr propose quelques fonctions permettant de
calculer des statistiques simples pondérées\footnote{Les fonctions
\rfunc{wtd.mean} et \rfunc{wtd.var} sont des copies conformes des
fonctions du même nom de l'extension \textsf{Hmisc} de Frank
Harrel. \textsf{Hmisc} étant une extension <<~de taille~>>, on a
préféré recopié les fonctions pour limiter le poids des dépendances.}~:
\begin{description}
\item[\rfunc{wtd.mean}] moyenne pondérée
\item[\rfunc{wtd.var}] variance pondérée
\item[\rfunc{wtd.table}] tris à plat et tris croisés pondérés
\end{description}
On les utilise de la manière suivante~:
<<wtdmean,warning=FALSE,message=FALSE,cache=FALSE>>=
library(questionr)
mean(d$age)
wtd.mean(d$age, weights=d$poids)
wtd.var(d$age, weights=d$poids)
@
Pour les tris à plat, on utilise la fonction \rfunc{wtd.table} à
laquelle on passe la variable en paramètre~:
<<>>=
wtd.table(d$sexe, weights=d$poids)
@
Pour un tri croisé, il suffit de passer deux variables en paramètres~:
<<>>=
wtd.table(d$sexe, d$hard.rock, weights=d$poids)
@
Ces fonctions admettent notamment les deux options suivantes~:
\begin{description}
\item[\texttt{na.rm}] si \texttt{TRUE}, on ne conserve que les
observations sans valeur manquante
\item[\texttt{normwt}] si \texttt{TRUE}, on normalise les poids pour
que les effectifs totaux pondérés soient les mêmes que les effectifs
initiaux. Il faut utiliser cette option, notamment si on souhaite
appliquer un test sensible aux effectifs comme le $\chi^2$.
\end{description}
Ces fonctions rendent possibles l'utilisation des statistiques
descriptives les plus simples et le traitement des tableaux croisés
(les fonctions \rfunc{lprop}, \rfunc{cprop} ou \rfunc{chisq.test}
peuvent être appliquées au résultat d'un \rfunc{wtd.table}) mais
restent limitées en termes de tests statistiques ou de
graphiques\ldots
\section{L'extension \textsf{survey}}
L'extension \textsf{survey} est spécialement dédiée au traitement
d'enquêtes ayant des techniques d'échantillonnage et de pondération
potentiellement très complexes. L'extension s'installe comme la
plupart des autres~:
<<eval=FALSE>>=
install.packages("survey",dep=TRUE)
@
Le site officiel (en anglais) comporte beaucoup d'informations, mais
pas forcément très accessibles~:
\url{http://faculty.washington.edu/tlumley/survey/}
Pour utiliser les fonctionnalités de l'extension, on doit d'abord
définir un \textit{design} de notre enquête. C'est-à-dire indiquer
quel type de pondération nous souhaitons lui appliquer. Dans notre cas
nous utilisons le \textit{design} le plus simple, avec une variable de
pondération déjà calculée. Ceci se fait à l'aide de la fonction
\rfunc{svydesign}~:
<<>>=
library(survey)
dw <- svydesign(ids=~1,data=d,weights=~d$poids)
@
Cette fonction crée un nouvel objet, que nous avons nommé
\texttt{dw}. Cet objet n'est pas à proprement parler un tableau de
données, mais plutôt un tableau de données \textit{plus} une méthode
de pondération. \texttt{dw} et \texttt{d} sont des objets distincts,
les opérations effectuées sur l'un n'ont pas d'influence sur l'autre.
On peut cependant retrouver le contenu de \texttt{d} depuis
\texttt{dw} en utilisant \texttt{dw\$variables}~:
<<>>=
mean(d$age)
mean(dw$variables$age)
@
Lorsque notre \textit{design} est déclaré, on peut lui appliquer une
série de fonctions permettant d'effectuer diverses opérations
statistiques en tenant compte de la pondération. On citera notamment~:
\begin{description}
\item[\rfunc{svymean}, \rfunc{svyvar}, \rfunc{svytotal}] statistiques univariées
\item[\rfunc{svytable}] tableaux croisés
\item[\rfunc{svychisq}] test du $\chi^2$
\item[\rfunc{svyby}] statistiques selon un facteur
\item[\rfunc{svyglm}] modèles linéaires généralisés
\item[\rfunc{svyplot}, \rfunc{svyhist}, \rfunc{svyboxplot}] fonctions graphiques
\end{description}
D'autres fonctions sont disponibles, comme \texttt{svyratio}, mais elles ne seront pas abordées ici.
Pour ne rien arranger, ces fonctions prennent leurs arguments sous
forme de formules, c'est-à-dire pas de la manière habituelle. En
général l'appel de fonction se fait en spécifiant d'abord les
variables d'intérêt sous forme de formule, puis l'objet \textit{design}.
Voyons tout de suite quelques exemples~:
<<>>=
svymean(~age, dw)
svyvar(~heures.tv, dw, na.rm=TRUE)
svytable(~sexe, dw)
svytable(~sexe+clso, dw)
@
En particulier, les tris à plat se déclarent en passant comme argument
le nom de la variable précédé d'un symbole \texttt{\~}, tandis que les
tableaux croisés utilisent les noms des deux variables séparés par un
\texttt{+} et précédés par un \texttt{\~}.
On peut récupérer le tableau issu de \rfunc{svytable} dans un objet et
le réutiliser ensuite comme n'importe quel tableau croisé~:
<<>>=
tab <- svytable(~sexe+clso, dw)
tab
lprop(tab)
svychisq(~sexe + clso, dw)
@
Les fonctions \rfunc{lprop} et \rfunc{cprop} de \questionr
\marqr sont donc tout à fait compatibles avec l'utilisation de
\textsf{survey}. La fonction \rfunc{freq} peut également être utilisée
si on lui passe en argument non pas la variable elle-même, mais son
tri à plat obtenu avec \rfunc{svytable}~:
<<>>=
tab <- svytable(~peche.chasse, dw)
freq(tab, total=TRUE)
@
Par contre, il \textbf{ne faut pas} utiliser \rfunc{chisq.test} sur un tableau
généré par \rfunc{svytable}. Les effectifs étant extrapolés à partir de la
pondération, les résultats du test seraient complètement faussés. Si on veut
faire un test du $\chi^2$ sur un tableau croisé pondéré, il faut utiliser
\rfunc{svychisq}~:
<<>>=
svychisq(~sexe + clso, dw)
@
Le principe de la fonction \rfunc{svyby} est similaire à celui de \rfunc{tapply}
(voir section \ref{sec_tapply} \vpageref{sec_tapply}). Elle permet de calculer
des statistiques selon plusieurs sous-groupes définis par un facteur.
Par exemple~:
<<>>=
svyby(~age, ~sexe, dw, svymean)
@
Enfin, \textsf{survey} est également capable de produire des
graphiques à partir des données pondérées. Des exemples sont donnés
figure~\ref{fig_surveyplot} \vpageref{fig_surveyplot}.
\begin{figure}
<<>>=
par(mfrow=c(2,2))
svyplot(~age+heures.tv,dw,col="red",main="Bubble plot")
svyhist(~heures.tv, dw, col="peachpuff", main="Histogramme")
svyboxplot(age~1,dw,main="Boxplot simple", ylab="Âge")
svyboxplot(age~sexe,dw,main="Boxplot double", ylab="Âge", xlab="Sexe")
@
\caption{Fonctions graphiques de l'extension \textsf{survey}}
\label{fig_surveyplot}
\end{figure}
\section{Conclusion}
En attendant mieux, la gestion de la pondération sous \R n'est sans
doute pas ce qui se fait de plus pratique et de plus simple. On pourra
quand même donner les conseils suivants~:
\begin{itemize}
\item utiliser les options de pondération des fonctions usuelles ou les
fonctions d'extensions comme \questionr pour les cas les
plus simples~;
\item si on utilise \textsf{survey}, effectuer tous les recodages et
manipulations sur les données non pondérées autant que possible~;
\item une fois les recodages effectués, on déclare le \textit{design}
et on fait les analyses en tenant compte de la pondération~;
\item surtout ne jamais modifier les variables du
\textit{design}. Toujours effectuer recodages et manipulations sur
les données non pondérées, puis redéclarer le \textit{design} pour que
les mises à jour effectuées soient dis