L’objectif de ce troisième et dernier module est de réutiliser dans un cadre métier les briques élémentaires du langage introduites dans le module précédent:
data.frame
et de ses relations avec les vecteurs, les matrices et les listes;En dernière partie, des liens complémentaires sont fournis vers le support de la formation R perfectionnement ainsi que vers des exemples d’utilisation plus spécifiques du logiciel (analyse de données multidimensionnelle, régression).
data.frame
Dans R, la majeure partie des données statistiques se présente sous la forme de data.frame
: ces objets permettent en effet de représenter sous la forme d’une table (i.e. d’un objet à deux dimensions) des données de nature tant quantitative (variables numériques) que qualitative (variables de type caractère ou facteur).
Pour créer un objet de type data.frame
, il suffit d’utiliser la fonction data.frame()
.
# Création du data.frame df1
df1 <- data.frame(
var1 = 1:10
, var2 = letters[1:10]
, var3 = rep(c(TRUE, FALSE), times = 5)
)
# Caractéristiques de df1
str(df1)
## 'data.frame': 10 obs. of 3 variables:
## $ var1: int 1 2 3 4 5 6 7 8 9 10
## $ var2: Factor w/ 10 levels "a","b","c","d",..: 1 2 3 4 5 6 7 8 9 10
## $ var3: logi TRUE FALSE TRUE FALSE TRUE FALSE ...
# Premières lignes de df1
head(df1)
## var1 var2 var3
## 1 1 a TRUE
## 2 2 b FALSE
## 3 3 c TRUE
## 4 4 d FALSE
## 5 5 e TRUE
## 6 6 f FALSE
Il est impératif que tous les éléments qui composent un data.frame
soient de même longueur.
# Création du data.frame df3
df3 <- data.frame(
var1 = 1:10
, var2 = 1:15
)
## Error in data.frame(var1 = 1:10, var2 = 1:15): les arguments impliquent des nombres de lignes différents : 10, 15
Remarque Par défaut, la fonction data.frame()
convertit les variables caractères en facteurs (cf. module 2). Pour éviter ce comportement (pas toujours souhaitable), il suffit d’utiliser l’argument stringsAsFactors = FALSE
.
# Création du data.frame df2
df2 <- data.frame(
var1 = 1:10
, var2 = letters[1:10]
, var3 = rep(c(TRUE, FALSE), times = 5)
, stringsAsFactors = FALSE
)
# Caractéristiques de df2
str(df2)
## 'data.frame': 10 obs. of 3 variables:
## $ var1: int 1 2 3 4 5 6 7 8 9 10
## $ var2: chr "a" "b" "c" "d" ...
## $ var3: logi TRUE FALSE TRUE FALSE TRUE FALSE ...
# Note : dans df2, var2 est de type caractère alors que dans
# df1 elle a été automatiquement convertie en factor.
Pour empêcher la conversion de caractères en facteurs pour toute une session, il suffit de modifier l’option globale stringsAsFactors
.
# Modification de l'option globale stringsAsFactors
options(stringsAsFactors = FALSE)
# Désormais l'option stringsAsFactors n'est plus nécessaire
# dans chaque appel de fonction
df3 <- data.frame(
var1 = 1:10
, var2 = letters[1:10]
, var3 = rep(c(TRUE, FALSE), times = 5)
)
str(df3)
## 'data.frame': 10 obs. of 3 variables:
## $ var1: int 1 2 3 4 5 6 7 8 9 10
## $ var2: chr "a" "b" "c" "d" ...
## $ var3: logi TRUE FALSE TRUE FALSE TRUE FALSE ...
Du point de vue de sa structure, un data.frame
est en réalité une liste dont tous les éléments ont la même longueur : c’est ce qui permet de le représenter sous la forme d’un tableau à deux dimensions.
# Un data.frame est une liste...
is.list(df1)
## [1] TRUE
# ... dont tous les éléments sont de même longueur
lapply(df1, length)
## $var1
## [1] 10
##
## $var2
## [1] 10
##
## $var3
## [1] 10
De ce fait, les data.frame
empruntent leurs caractéristiques tantôt aux listes, tantôt aux matrices :
Comme une matrice, un data.frame
a deux dimensions (fonction dim()
) ; mais comme une liste, sa longueur (fonction length()
) correspond à son nombre d’éléments (son nombre de variables).
# Dimensions de df1 : comme une matrice
dim(df1)
## [1] 10 3
nrow(df1)
## [1] 10
ncol(df1)
## [1] 3
# Longueur de df1 : comme une liste
length(df1)
## [1] 3
Comme avec une matrice, on accède aux noms de lignes et de colonne d’un data.frame
avec les fonctions rownames()
et colnames()
; mais comme avec une liste, les noms de colonnes sont aussi directement accessibles avec names()
.
# rownames() et colnames() : comme avec une matrice
rownames(df1)
## [1] "1" "2" "3" "4" "5" "6" "7" "8" "9" "10"
colnames(df1)
## [1] "var1" "var2" "var3"
# names() : comme avec une liste
names(df1)
## [1] "var1" "var2" "var3"
Comme avec une matrice, il est possible d’accéder aux éléments d’un data.frame
en indiquant leurs deux positions dans un opérateur [
; mais comme avec une liste, il est également possible d’utiliser les opérateurs [[
et $
.
df1
## var1 var2 var3
## 1 1 a TRUE
## 2 2 b FALSE
## 3 3 c TRUE
## 4 4 d FALSE
## 5 5 e TRUE
## 6 6 f FALSE
## 7 7 g TRUE
## 8 8 h FALSE
## 9 9 i TRUE
## 10 10 j FALSE
# On cherche à accéder à l'élément en ligne 8, colonne 2 de df1
# - comme une matrice : avec `[` et deux positions
df1[8, 2]
## [1] h
## Levels: a b c d e f g h i j
df1[8, "var2"]
## [1] h
## Levels: a b c d e f g h i j
# - comme une liste : avec `[[` pour sélectionner la colonne,
# puis [ pour sélectionner la ligne
df1[[2]][8]
## [1] h
## Levels: a b c d e f g h i j
df1[["var2"]][8]
## [1] h
## Levels: a b c d e f g h i j
# - comme une liste : avec `$` pour sélectionner la colonne,
# puis [ pour sélectionner la ligne
df1$var2[8]
## [1] h
## Levels: a b c d e f g h i j
Les fonctions as.matrix()
, as.list()
et as.data.frame()
permettent de convertir un data.frame
en liste ou en matrice, et inversement.
# Conversion de df1 en matrice
as.matrix(df1)
## var1 var2 var3
## [1,] " 1" "a" " TRUE"
## [2,] " 2" "b" "FALSE"
## [3,] " 3" "c" " TRUE"
## [4,] " 4" "d" "FALSE"
## [5,] " 5" "e" " TRUE"
## [6,] " 6" "f" "FALSE"
## [7,] " 7" "g" " TRUE"
## [8,] " 8" "h" "FALSE"
## [9,] " 9" "i" " TRUE"
## [10,] "10" "j" "FALSE"
# Note : au passage les variables ont toutes été converties
# en caractères, car une matrice ne peut avoir qu'un seul
# et unique type
# Conversion de df1 en liste
as.list(df1)
## $var1
## [1] 1 2 3 4 5 6 7 8 9 10
##
## $var2
## [1] a b c d e f g h i j
## Levels: a b c d e f g h i j
##
## $var3
## [1] TRUE FALSE TRUE FALSE TRUE FALSE TRUE FALSE TRUE FALSE
# Note : on n'a pas à proprement parler affaire ici à une
# "conversion" (un data.frame est une liste) mais plutôt
# à la suppression de certains attributs spécifiques aux
# data.frame (noms de ligne notamment)
rownames(df1)
## [1] "1" "2" "3" "4" "5" "6" "7" "8" "9" "10"
rownames(as.list(df1))
## NULL
# Conversion d'une matrice en data.frame
as.data.frame(matrix(1:10, ncol = 5))
## V1 V2 V3 V4 V5
## 1 1 3 5 7 9
## 2 2 4 6 8 10
# Conversion d'une liste en data.frame
as.data.frame(list(a = 1:5, b = letters[5:1]))
## a b
## 1 1 e
## 2 2 d
## 3 3 c
## 4 4 b
## 5 5 a
# Note : dans ce cas il est également impératif
# que tous les éléments de la liste aient bien la même
# longueur.
Ce cas pratique aborde plusieurs manipulations courantes de sélection de variables et d’observations dans une table. Comme la plupart des cas pratiques de ce module, il repose sur l’utilisation des données de l’enquête Emploi en continu 2012 restreinte au quatrième trimestre et aux individus en première ou sixième interrogation. Ces données correspondent au fichier eect4.rds
contenu dans le fichier donnees.zip.
Après avoir modifié le répertoire de travail avec setwd()
, utilisez la fonction readRDS()
pour charger le fichier eect4.rds
dans l’objet eec
(cf. la remarque finale du module 1 pour l’utilisation de la fonction readRDS()
).
Pour simplifier le travail sur cette table, on souhaite normaliser la casse des noms de variable. Proposez une méthode pour passer l’ensemble des noms de variable en minuscules et appliquez-la.
On souhaite créer deux nouvelles tables ne contenant que les variables sur lesquelles portent différents aspects de l’étude :
eec2
qui ne contienne que les variables ident
, noi
, acteu
et extri1613
.
eec3
qui contienne toutes les variables de eec
à l’exception de cse
.
On souhaite désormais créer une nouvelle table eec4
contenant toutes les variables mais uniquement pour les individus appartenant à la population active (acteu
vaut "1"
ou "2"
). Comment procéderiez-vous ?
data.frame
Pour créer une nouvelle variable dans un data.frame
, le plus simple est d’utiliser l’opérateur $
.
# Création du data.frame df5
df5 <- data.frame(
var1 = letters[1:4]
, var2 = rep(c(FALSE, TRUE), times = 2)
, stringsAsFactors = FALSE
)
df5
## var1 var2
## 1 a FALSE
## 2 b TRUE
## 3 c FALSE
## 4 d TRUE
# Ajout de la variable var3 avec $
df5$var3 <- (1:4)^2
df5
## var1 var2 var3
## 1 a FALSE 1
## 2 b TRUE 4
## 3 c FALSE 9
## 4 d TRUE 16
Pour créer une variable à partir d’une ou plusieurs autres de la table, il suffit d’utiliser l’opérateur $
plusieurs fois.
# Création de la variable var4 à partir de var3
df5$var4 <- df5$var3 * 2
df5
## var1 var2 var3 var4
## 1 a FALSE 1 2
## 2 b TRUE 4 8
## 3 c FALSE 9 18
## 4 d TRUE 16 32
# Conversion de var2 de logique vers numérique
df5$var2 <- as.numeric(df5$var2)
df5
## var1 var2 var3 var4
## 1 a 0 1 2
## 2 b 1 4 8
## 3 c 0 9 18
## 4 d 1 16 32
# Note : modifier à la volée une variable existante ne pose
# aucun problème
Pour effectuer un recodage manuel selon une ou plusieurs conditions (comme un IF THEN ELSE dans SAS), trois méthodes sont disponibles :
Pour les variables dichotomiques uniquement, utiliser des opérateurs logiques pour créer un nouveau vecteur.
# Création de la variable var5 valant TRUE si var4 > 10 et var2 = 1
df5$var5 <- df5$var4 > 10 & df5$var2 == 1
df5
## var1 var2 var3 var4 var5
## 1 a 0 1 2 FALSE
## 2 b 1 4 8 FALSE
## 3 c 0 9 18 FALSE
## 4 d 1 16 32 TRUE
Créer la variable recodée progressivement en utilisant l’opérateur [
.
# Création de la variable var6 identique à var5
df5$var6 <- "Non"
df5$var6[df5$var4 > 10 & df5$var2 == 1] <- "Oui"
df5
## var1 var2 var3 var4 var5 var6
## 1 a 0 1 2 FALSE Non
## 2 b 1 4 8 FALSE Non
## 3 c 0 9 18 FALSE Non
## 4 d 1 16 32 TRUE Oui
Utiliser la fonction ifelse()
.
# Création de la variable var7 identique à var5 et var6
df5$var7 <- ifelse(df5$var4 > 10 & df5$var2 == 1, "Oui", "Non")
df5
## var1 var2 var3 var4 var5 var6 var7
## 1 a 0 1 2 FALSE Non Non
## 2 b 1 4 8 FALSE Non Non
## 3 c 0 9 18 FALSE Non Non
## 4 d 1 16 32 TRUE Oui Oui
La fonction ifelse()
prend trois arguments : l’expression logique à évaluer, la valeur à renvoyer si l’expression est vraie, la valeur à renvoyer si l’expression est fausse. Il est possible d’imbriquer des fonctions ifelse()
pour effectuer des recodages complexes.
Remarque Savoir tirer parti de la fonction within()
Quand on met en oeuvre un recodage, on est fréquemment amené à répéter le nom du data.frame
sur lequel on travaille. La fonction within()
permet d’alléger l’écriture d’un recodage et de faciliter la compréhension d’un code en évitant cette répétition.
# Concaténation manuelle des variables var1 à var4
df5$var7 <- paste0(df5$var1, df5$var2, df5$var3, df5$var4)
# Syntaxe allégée avec la fonction within()
# Création de la variable var5, concaténation de
# toutes les autres variables de la table df5
df5 <- within(df5, {
var8 <- paste0(var1, var2, var3, var4)
})
df5[, c("var7", "var8")]
## var7 var8
## 1 a012 a012
## 2 b148 b148
## 3 c0918 c0918
## 4 d11632 d11632
Le premier argument de within()
est le nom du data.frame
sur lequel porte le recodage, le second est la série d’instructions à appliquer (les accolades sont obligatoires s’il y a plus d’une instruction).
Ce cas pratique vise à appliquer les opérations de création et de modification de variables présentées dans cette partie à des données statistiques classiques. Comme le précédent, il porte sur les données de l’enquête Emploi en continu au 2015T4.
La variable cse
code la Profession et catégorie socioprofessionnelle (PCS) des individus en 42 postes (cf. cette page pour plus de détails). On souhaite créer la variable agrégée cs
qui ne conserve que la première position de la nomenclature.
Proposez une première méthode (un peu fastidieuse) s’appuyant sur des recodages manuels avec l’opérateur [
.
Effectuez le même recodage en utilisant la fonction substr()
.
La variable de position sur le marché du travail (acteu
) comporte des valeurs manquantes dans le fichier eec
à votre disposition. On souhaite imputer cette variable de façon déterministe :
acteu
vaut "1"
) ;acteu
vaut "3"
).Remarque Le fichier original de l’enquête Emploi en continu ne comporte aucune valeur manquante pour la variable acteu
, celles-ci ont été ajoutées pour l’exercice.
Utilisez la fonction table()
pour affichez le nombre de valeurs NA
dans la variable acteu
. Créez la table eec_pb
ne comportant que les individus pour lesquels la variable acteu
vaut NA
.
Dans la table eec
, créez la variable redressée acteu_red
en mettant en oeuvre la procédure d’imputation (très frustre) décrite ci-dessus.
Recréez la table eec_pb
et contrôlez que l’imputation s’est déroulée correctement (en vérifiant que les valeurs imputées sont cohérentes avec l’âge des individus).
Le vecteur de poids de l’enquête (variable extri1613
) présente des valeurs extrêmes relativement élevées. Afin d’éviter que les estimations ne soient trop affectées par quelques individus atypiques, on souhaite limiter le poids des individus en les “rabotant” à la valeur du 99ème percentile.
Utilisez la fonction quantile()
pour calculer le 99ème percentile de la distribution de extri1613
.
Récupérer la valeur du 99ème percentile et utilisez-la pour créer une nouvelle pondération (newpond
) dans laquelle les poids ont été “rabotés” à son niveau.
data.frame
Comme pour les vecteurs ou les matrices, plusieurs opérations permettent de modifier la structure d’un data.frame
:
data.frame
avec order()
: contrairement aux vecteurs, il n’est pas possible d’utiliser la fonction sort()
pour trier un data.frame
. En revanche, la fonction order()
renvoie la permutation permettant de trier une table selon une ou plusieurs variables.# Création de la table df6
df6 <- data.frame(
var1 = letters[c(3, 4, 2, 5, 1, 5, 2, 4, 3, 1)]
, var2 = rnorm(10))
df6
## var1 var2
## 1 c -0.6264538
## 2 d 0.1836433
## 3 b -0.8356286
## 4 e 1.5952808
## 5 a 0.3295078
## 6 e -0.8204684
## 7 b 0.4874291
## 8 d 0.7383247
## 9 c 0.5757814
## 10 a -0.3053884
# Tri selon la variable var1
# - Etape 1 : obtention de la permutation correspondante
order(df6$var1)
## [1] 5 10 3 7 1 9 2 8 4 6
# Utilisée sur le vecteur df6$var1, cette permutation
# renvoie un vecteur trié
df6$var1
## [1] "c" "d" "b" "e" "a" "e" "b" "d" "c" "a"
order(df6$var1)
## [1] 5 10 3 7 1 9 2 8 4 6
df6$var1[order(df6$var1)]
## [1] "a" "a" "b" "b" "c" "c" "d" "d" "e" "e"
# - Etape 2 : utilisation de la permutation pour trier df6
df6[order(df6$var1), ]
## var1 var2
## 5 a 0.3295078
## 10 a -0.3053884
## 3 b -0.8356286
## 7 b 0.4874291
## 1 c -0.6264538
## 9 c 0.5757814
## 2 d 0.1836433
## 8 d 0.7383247
## 4 e 1.5952808
## 6 e -0.8204684
# Tri selon la variable var1 puis la variable var2
# - Etape 1 : obtention de la permutation correspondante
order(df6$var1, df6$var2)
## [1] 10 5 3 7 1 9 2 8 6 4
# - Etape 2 : utilisation de la permutation pour trier
df6[order(df6$var1, df6$var2), ]
## var1 var2
## 10 a -0.3053884
## 5 a 0.3295078
## 3 b -0.8356286
## 7 b 0.4874291
## 1 c -0.6264538
## 9 c 0.5757814
## 2 d 0.1836433
## 8 d 0.7383247
## 6 e -0.8204684
## 4 e 1.5952808
# Tri selon la variable var1 puis les valeurs décroissantes
# de var2
df6 <- df6[order(df6$var1, - df6$var2), ]
df6
## var1 var2
## 5 a 0.3295078
## 10 a -0.3053884
## 7 b 0.4874291
## 3 b -0.8356286
## 9 c 0.5757814
## 1 c -0.6264538
## 8 d 0.7383247
## 2 d 0.1836433
## 4 e 1.5952808
## 6 e -0.8204684
unique()
: la fonction unique()
utilisée sur les vecteurs est également applicable aux data.frame
.# Ajout de la variable var3
df6$var3 <- rep(1:2, each = 5)
df6
## var1 var2 var3
## 5 a 0.3295078 1
## 10 a -0.3053884 1
## 7 b 0.4874291 1
## 3 b -0.8356286 1
## 9 c 0.5757814 1
## 1 c -0.6264538 2
## 8 d 0.7383247 2
## 2 d 0.1836433 2
## 4 e 1.5952808 2
## 6 e -0.8204684 2
# Sélection de toutes les valeurs distinctes de var1 et var3
unique(df6[,c("var1", "var3")])
## var1 var3
## 5 a 1
## 7 b 1
## 9 c 1
## 1 c 2
## 8 d 2
## 4 e 2
data.frame
avec les fonctions cbind()
et rbind()
.# Création du data.frame df7
df7 <- data.frame(
var1 = c("f","f")
, var2 = rnorm(2)
, var3 = 3
)
df7
## var1 var2 var3
## 1 f 1.5117812 3
## 2 f 0.3898432 3
# Création du data.frame df8 par concaténation des lignes
# de df6 et de df7
df8 <- rbind(df6, df7)
df8
## var1 var2 var3
## 5 a 0.3295078 1
## 10 a -0.3053884 1
## 7 b 0.4874291 1
## 3 b -0.8356286 1
## 9 c 0.5757814 1
## 1 c -0.6264538 2
## 8 d 0.7383247 2
## 2 d 0.1836433 2
## 4 e 1.5952808 2
## 6 e -0.8204684 2
## 11 f 1.5117812 3
## 21 f 0.3898432 3
# Note : il faut que les deux data.frame aient exactement
# les mêmes variables avec le même nom pour que cela fonctionne
rbind(df6, df7[, c("var1", "var3")])
## Error in rbind(deparse.level, ...): les nombres de colonnes des arguments ne correspondent pas
merge()
permet de fusionner deux data.frame
(pas plus) sur la base d’un identifiant. À noter que les tables n’ont pas besoin d’être triées au préalable.# Création du data.frame df9
df9 <- data.frame(
var3 = 2:4
, var4 = c(TRUE, FALSE, TRUE)
)
df9
## var3 var4
## 1 2 TRUE
## 2 3 FALSE
## 3 4 TRUE
# Fusion de df8 et de df9 selon la variable var3
merge(df8, df9, by = "var3")
## var3 var1 var2 var4
## 1 2 c -0.6264538 TRUE
## 2 2 d 0.7383247 TRUE
## 3 2 d 0.1836433 TRUE
## 4 2 e 1.5952808 TRUE
## 5 2 e -0.8204684 TRUE
## 6 3 f 1.5117812 FALSE
## 7 3 f 0.3898432 FALSE
# Par défaut, merge() se restreint aux valeurs communes aux deux tables.
# Conservation de toutes les observations de df8 avec all.x = TRUE
merge(df8, df9, by = "var3", all.x = TRUE)
## var3 var1 var2 var4
## 1 1 a 0.3295078 NA
## 2 1 a -0.3053884 NA
## 3 1 b 0.4874291 NA
## 4 1 b -0.8356286 NA
## 5 1 c 0.5757814 NA
## 6 2 c -0.6264538 TRUE
## 7 2 d 0.7383247 TRUE
## 8 2 d 0.1836433 TRUE
## 9 2 e 1.5952808 TRUE
## 10 2 e -0.8204684 TRUE
## 11 3 f 1.5117812 FALSE
## 12 3 f 0.3898432 FALSE
# Conservation de toutes les observations de df9 avec all.y = TRUE
merge(df8, df9, by = "var3", all.y = TRUE)
## var3 var1 var2 var4
## 1 2 c -0.6264538 TRUE
## 2 2 d 0.7383247 TRUE
## 3 2 d 0.1836433 TRUE
## 4 2 e 1.5952808 TRUE
## 5 2 e -0.8204684 TRUE
## 6 3 f 1.5117812 FALSE
## 7 3 f 0.3898432 FALSE
## 8 4 <NA> NA TRUE
À noter qu’il peut y avoir plusieurs variables de fusion et qu’il n’est pas indispensable qu’elles aient le même nom.
# Création du data.frame df10
df10 <- data.frame(
v1 = c("c","f")
, v3 = c(2, 3)
, v5 = c("Rouge", "Bleu")
)
df10
## v1 v3 v5
## 1 c 2 Rouge
## 2 f 3 Bleu
# Fusion de df8 et de df10
merge(df8, df10, by.x = c("var3", "var1"), by.y = c("v3", "v1"), all = TRUE)
## var3 var1 var2 v5
## 1 1 a 0.3295078 <NA>
## 2 1 a -0.3053884 <NA>
## 3 1 b 0.4874291 <NA>
## 4 1 b -0.8356286 <NA>
## 5 1 c 0.5757814 <NA>
## 6 2 c -0.6264538 Rouge
## 7 2 d 0.7383247 <NA>
## 8 2 d 0.1836433 <NA>
## 9 2 e -0.8204684 <NA>
## 10 2 e 1.5952808 <NA>
## 11 3 f 1.5117812 Bleu
## 12 3 f 0.3898432 Bleu
À partir de la table eec
, on souhaite produire une nouvelle table (eec5
) qui ne comporte qu’un individu par ménage, le plus âgé. Les ménages sont identifiés par la variable ident
et la variable age
code l’âge des individus.
Comment détermineriez-vous le nombre de ménages dans la table eec
?
On cherche d’abord à constituer une table ne comportant qu’un seul individu par ménage, quel que soit son âge. Comment procéderiez-vous ?
Comment adapteriez-vous la réponse à la question précédente pour sélectionner l’individu le plus âgé du ménage (sans chercher à maîtriser celui qui est sélectionné quand plusieurs membres d’un même ménage ont le même âge) ?
(Optionnel) Comment adapteriez-vous la réponse à la question précédente pour effectuer un tirage au sort quand plusieurs membres d’un même ménage ont le même âge ?
Retour sur les PCS. Entre le niveau de la variable cse
(niveau 3) et le niveau le plus agrégé de la variable cs
créée dans le cas pratique 3.1 (niveau 1), il existe un niveau intermédiaire (niveau 2). La correspondance entre le niveau 3 et le niveau 2 n’est pas directe, et en règle générale on utilise la table de passage pcs2003_c_n4_n1.dbf
(téléchargée depuis le site de l’Insee) pour la réaliser.
Utilisez le package foreign
et la fonction read.dbf
pour importer cette table dans R. La nomenclature comporte quatre niveaux, mais le quatrième (variable N4
) ne nous intéresse pas : agrégez la table de façon à ne conserver que les valeurs distinctes pour les niveaux 2 et 3 de la nomenclature.
Utilisez la fonction merge()
pour fusionner cette table de passage avec le fichier eec
et créer une nouvelle table (eec6
) contenant une variable supplémentaire correspondant au niveau 2 de la PCS.
(Difficile) À partir de la table de passage agrégée à la sous-question i., créez le vecteur n2
dont les éléments sont les valeurs de la variable N2 et dont les noms sont les valeurs de la variable N3. Comment pourriez-vous utiliser ce vecteur pour obtenir le même résultat qu’à la question ii. ?
data.frame
La proximité des data.frame
avec les listes se retrouve dans le type d’opérations qu’il est possible de leur appliquer : comme avec les listes, il est possible d’utiliser les fonctions lapply()
et sapply()
, qui s’appliquent colonne par colonne.
df11 <- data.frame(
var1 = 1:5
, var2 = 11:15
, var3 = 21:25
)
df11
## var1 var2 var3
## 1 1 11 21
## 2 2 12 22
## 3 3 13 23
## 4 4 14 24
## 5 5 15 25
# lapply(), sapply() : comme une liste
lapply(df11, sum)
## $var1
## [1] 15
##
## $var2
## [1] 65
##
## $var3
## [1] 115
sapply(df11, mean)
## var1 var2 var3
## 3 13 23
Une des opérations les plus utiles consiste à appliquer une même fonction à des groupes d’observations définis par les modalités d’une autre variables (comme avec une instruction BY dans SAS).
Exemple Âge moyen par région, salaire moyen par sexe, etc.
Plusieurs fonctions de R permettent de mener à bien ce type d’opération :
la fonction aggregate()
;
df6
## var1 var2 var3
## 5 a 0.3295078 1
## 10 a -0.3053884 1
## 7 b 0.4874291 1
## 3 b -0.8356286 1
## 9 c 0.5757814 1
## 1 c -0.6264538 2
## 8 d 0.7383247 2
## 2 d 0.1836433 2
## 4 e 1.5952808 2
## 6 e -0.8204684 2
# On souhaite calculer la moyenne de var2
# selon les modalités de var3
aggregate(df6$var2, list(df6$var1), mean)
## Group.1 x
## 1 a 0.01205969
## 2 b -0.17409978
## 3 c -0.02533623
## 4 d 0.46098401
## 5 e 0.38740621
la fonction tapply()
;
tapply(df6$var2, df6$var1, mean)
## a b c d e
## 0.01205969 -0.17409978 -0.02533623 0.46098401 0.38740621
la fonction split()
combinée à un lapply()
ou un sapply()
.
# La fonction split(x, f) "éclate" le data.frame x en une
# liste de data.frame selon les modalités du factor f
split(df6, df6$var1)
## $a
## var1 var2 var3
## 5 a 0.3295078 1
## 10 a -0.3053884 1
##
## $b
## var1 var2 var3
## 7 b 0.4874291 1
## 3 b -0.8356286 1
##
## $c
## var1 var2 var3
## 9 c 0.5757814 1
## 1 c -0.6264538 2
##
## $d
## var1 var2 var3
## 8 d 0.7383247 2
## 2 d 0.1836433 2
##
## $e
## var1 var2 var3
## 4 e 1.5952808 2
## 6 e -0.8204684 2
# Il ne reste alors plus qu'à appliquer
# à chaque élément de la liste ainsi produite
# la fonction souhaitée par le biais d'un sapply()
sapply(split(df6, df6$var1), function(x) mean(x$var2))
## a b c d e
## 0.01205969 -0.17409978 -0.02533623 0.46098401 0.38740621
Remarques
# Installation et chargement de la bibliothèque de test
# de performance microbenchmark
# install.packages("microbenchmark")
library(microbenchmark)
# Compararison des trois méthodes + variante optimisée de sapply()
microbenchmark(times = 1000
, aggregate = aggregate(df6$var2, list(df6$var1), mean)
, sapply = sapply(split(df6, df6$var1), function(x) mean(x$var2))
, tapply = tapply(df6$var2, df6$var1, mean)
, sapply2 = sapply(split(df6$var2, df6$var1), mean)
)
## Unit: microseconds
## expr min lq mean median uq max neval
## aggregate 804.059 954.1130 1273.1944 1054.7315 1312.2340 7488.553 1000
## sapply 385.801 461.3605 630.4129 514.8380 619.4915 5815.864 1000
## tapply 142.777 180.1195 277.9384 207.6895 257.7220 17500.783 1000
## sapply2 114.882 143.5145 205.5141 164.6825 201.5695 3096.067 1000
sqldf
permet d’utiliser le langage SQL dans R (à l’image de la PROC SQL dans SAS), aussi bien pour des agrégations (par groupe notamment) que pour des fusions.
On souhaite calculer le taux de chômage au niveau national et régional. Le taux de chômage est défini par le ratio du nombre total d’individus au chômage (acteu %in% "2"
) sur la taille de la population active (acteu %in% c("1", "2")
).
Remarque Le fichier utilisé ici ne comporte que les logements en première ou sixième interrogation : les estimations effectuées dans ce cas pratique n’ont donc aucune raison de coïncider avec les estimations officielles (qui par ailleurs sont CVS-CJO).
Calculez le taux de chômage national, d’abord non-pondéré puis pondéré par la variable extri1613
.
Utilisez les fonctions aggregate()
, tapply()
et sapply()
(avec split()
dans le dernier cas) pour calculer un taux de chômage non-pondéré et par région (variable reg
).
Utilisez la fonction sapply()
avec split()
pour calculer un taux de chômage pondéré et par région.
Pour des raisons de stockage et de performances, on souhaite optimiser le type des variables de l’objet eec
. En effet, R manipule beaucoup plus efficacement les variables de type numérique que les variables de type caractère.
Déterminer sous la forme d’un vecteur logique quelles variables de l’objet eec
sont de type caractère.
Créez la table eec7
dans lequel toutes les variables de type caractère de eec
à l’exception de ident et noi sont converties en variables de type numérique.
Pour chaque variable numérique de eec7
, testez si la conversion en nombre entier (grâce à la fonction as.integer()
) est sans perte. Quand c’est le cas, convertissez la variable en nombre entier.
La plupart des fonctions permettant de calculer des statistiques descriptives ont été présentées tout au long de la formation : table()
, summary()
, etc. Cette partie revient sur l’utilisation de ces fonctions dans une perspective proprement statistique, en élargissant leur utilisation au cas des données pondérées.
L’ensemble des éléments introduits dans cette partie sont mis en pratique sur les données de l’enquête Pisa 2012 (cf. dernière sous-partie).
La fonction table()
calcule les fréquences (non-pondérées) des modalités ou des croisements de modalités d’une ou plusieurs variables qualitatives.
# Fréquences des modalités de la variable pub3fp
# Signification des modalités :
# 1 : Fonction publique d'Etat
# 2 : Fonction publique territoriale
# 3 : Fonction publique hospitalitère
# 4 : Secteur privé
table(eec$pub3fp)
##
## 1 2 3 4
## 1415 1246 757 11701
# Utilisation de l'argument useNA pour afficher les valeurs manquantes
table(eec$pub3fp, useNA = "always")
##
## 1 2 3 4 <NA>
## 1415 1246 757 11701 19794
# Croisement avec le sexe
table(eec$pub3fp, eec$sexe, useNA = "always")
##
## 1 2 <NA>
## 1 633 782 0
## 2 452 794 0
## 3 164 593 0
## 4 6234 5467 0
## <NA> 9099 10695 0
Pour améliorer l’affichage des résultats de la fonction table()
, le plus simple est de transformer les variables caractères utilisées en facteurs, au préalable ou directement dans la fonction table()
.
# Transformation de pub3fp en factor
eec$pub3fp <- factor(eec$pub3fp, labels = c(
"Fonction publique d'Etat"
, "Fonction publique territoriale"
, "Fonction publique hospitalière"
, "Secteur privé"
))
# Impact sur l'affichage de table()
table(eec$pub3fp, eec$sexe, useNA = "always")
##
## 1 2 <NA>
## Fonction publique d'Etat 633 782 0
## Fonction publique territoriale 452 794 0
## Fonction publique hospitalière 164 593 0
## Secteur privé 6234 5467 0
## <NA> 9099 10695 0
# Tranformation à la volée de eec$sexe en factor
table(eec$pub3fp, factor(eec$sexe, labels = c("Homme","Femme")), useNA = "always")
##
## Homme Femme <NA>
## Fonction publique d'Etat 633 782 0
## Fonction publique territoriale 452 794 0
## Fonction publique hospitalière 164 593 0
## Secteur privé 6234 5467 0
## <NA> 9099 10695 0
Les fonctions addmargins()
et prop.table()
permettent d’ajouter les marges et de calculer des pourcentages respectivement.
t <- table(eec$pub3fp, eec$sexe, useNA = "always")
# Ajout de marges avec la fonction addmargins()
addmargins(t)
##
## 1 2 <NA> Sum
## Fonction publique d'Etat 633 782 0 1415
## Fonction publique territoriale 452 794 0 1246
## Fonction publique hospitalière 164 593 0 757
## Secteur privé 6234 5467 0 11701
## <NA> 9099 10695 0 19794
## Sum 16582 18331 0 34913
# Calcul de pourcentages
prop.table(t) # Pourcentages de cellule
##
## 1 2 <NA>
## Fonction publique d'Etat 0.018130782 0.022398533 0.000000000
## Fonction publique territoriale 0.012946467 0.022742245 0.000000000
## Fonction publique hospitalière 0.004697391 0.016985077 0.000000000
## Secteur privé 0.178558130 0.156589236 0.000000000
## <NA> 0.260619254 0.306332885 0.000000000
prop.table(t, 1) # Pourcentages en ligne
##
## 1 2 <NA>
## Fonction publique d'Etat 0.4473498 0.5526502 0.0000000
## Fonction publique territoriale 0.3627608 0.6372392 0.0000000
## Fonction publique hospitalière 0.2166446 0.7833554 0.0000000
## Secteur privé 0.5327750 0.4672250 0.0000000
## <NA> 0.4596848 0.5403152 0.0000000
prop.table(t, 2) # Pourcentages en colonne
##
## 1 2 <NA>
## Fonction publique d'Etat 0.038173924 0.042659975
## Fonction publique territoriale 0.027258473 0.043314604
## Fonction publique hospitalière 0.009890242 0.032349572
## Secteur privé 0.375949825 0.298237958
## <NA> 0.548727536 0.583437892
La fonction chisq.test()
mène le test d’indépendance du \(\chi^2\).
# Test du chi2 sur le lien entre eec$pub3fp et eec$sexe
chisq.test(eec$pub3fp, eec$sexe)
##
## Pearson's Chi-squared test
##
## data: eec$pub3fp and eec$sexe
## X-squared = 401.45, df = 3, p-value < 2.2e-16
Au-delà de ces fonctions natives, le package descr
facilite considérablement l’analyse uni- et bivariée de variables qualitatives, en particulier quand les données ont à être pondérées (données d’enquête).
# Installation du package descr
# install.packages("descr")
# Chargement du package descr
library(descr)
La fonction freq()
présente les résultats d’un tri à plat de façon plus complète et plus naturelle et son argument w
permet de pondérer les calculs.
# Tri à plat non-pondéré sur la variable eec$pub3fp
freq(eec$pub3fp)
## eec$pub3fp
## Frequency Percent Valid Percent
## Fonction publique d'Etat 1415 4.053 9.359
## Fonction publique territoriale 1246 3.569 8.241
## Fonction publique hospitalière 757 2.168 5.007
## Secteur privé 11701 33.515 77.393
## NA's 19794 56.695
## Total 34913 100.000 100.000
# Tri à plat pondéré sur la variable eec$pub3fp
freq(eec$pub3fp, w = eec$extri1613)
## eec$pub3fp
## Frequency Percent Valid Percent
## Fonction publique d'Etat 2148336 4.254 9.453
## Fonction publique territoriale 1816318 3.596 7.992
## Fonction publique hospitalière 1095084 2.168 4.819
## Secteur privé 17666632 34.981 77.736
## NA's 27777229 55.000
## Total 50503600 100.000 100.000
De même, la fonction crosstab()
simplifie l’interprétation d’un tri croisé et l’utilisation de pondérations.
# Tri croisé non-pondéré des variables eec$pub3fp et eec$sexe
crosstab(eec$pub3fp, eec$sexe)
## Cell Contents
## |-------------------------|
## | Count |
## |-------------------------|
##
## =====================================================
## eec$sexe
## eec$pub3fp 1 2 Total
## -----------------------------------------------------
## Fonction publique d'Etat 633 782 1415
## -----------------------------------------------------
## Fonction publique territoriale 452 794 1246
## -----------------------------------------------------
## Fonction publique hospitalière 164 593 757
## -----------------------------------------------------
## Secteur privé 6234 5467 1.17e+04
## -----------------------------------------------------
## Total 7483 7636 1.512e+04
## =====================================================
# Tri croisé pondéré des variables eec$pub3fp et eec$sexe
crosstab(eec$pub3fp, eec$sexe, w = eec$extri1613)
## Cell Contents
## |-------------------------|
## | Count |
## |-------------------------|
##
## ================================================================
## eec$sexe
## eec$pub3fp 1 2 Total
## ----------------------------------------------------------------
## Fonction publique d'Etat 9.712e+05 1.177e+06 2.148e+06
## ----------------------------------------------------------------
## Fonction publique territoriale 6.663e+05 1.15e+06 1.816e+06
## ----------------------------------------------------------------
## Fonction publique hospitalière 2.426e+05 8.525e+05 1.095e+06
## ----------------------------------------------------------------
## Secteur privé 9.539e+06 8.127e+06 1.767e+07
## ----------------------------------------------------------------
## Total 1.142e+07 1.131e+07 2.273e+07
## ================================================================
# Ajout des pourcentages en ligne et en colonne
crosstab(eec$pub3fp, eec$sexe, w = eec$extri1613, prop.r = TRUE, prop.c = TRUE)
## Cell Contents
## |-------------------------|
## | Count |
## | Row Percent |
## | Column Percent |
## |-------------------------|
##
## ================================================================
## eec$sexe
## eec$pub3fp 1 2 Total
## ----------------------------------------------------------------
## Fonction publique d'Etat 971236 1177100 2148336
## 45.2% 54.8% 9.5%
## 8.5% 10.4%
## ----------------------------------------------------------------
## Fonction publique territoriale 666324 1149994 1816318
## 36.7% 63.3% 8.0%
## 5.8% 10.2%
## ----------------------------------------------------------------
## Fonction publique hospitalière 242581 852503 1095084
## 22.2% 77.8% 4.8%
## 2.1% 7.5%
## ----------------------------------------------------------------
## Secteur privé 9539319 8127313 17666632
## 54.0% 46.0% 77.7%
## 83.5% 71.9%
## ----------------------------------------------------------------
## Total 11419460 11306910 22726370
## 50.2% 49.8%
## ================================================================
# Test du chi2
crosstab(
eec$pub3fp, eec$sexe, w = eec$extri1613 / mean(eec$extri1613)
, prop.chisq = TRUE, chisq = TRUE
)
## Cell Contents
## |-------------------------|
## | Count |
## | Chi-square contribution |
## |-------------------------|
##
## ===========================================================
## eec$sexe
## eec$pub3fp 1 2 Total
## -----------------------------------------------------------
## Fonction publique d'Etat 671 814 1485
## 7.585 7.662
## -----------------------------------------------------------
## Fonction publique territoriale 461 795 1256
## 45.874 46.338
## -----------------------------------------------------------
## Fonction publique hospitalière 168 589 757
## 118.598 119.797
## -----------------------------------------------------------
## Secteur privé 6595 5618 12213
## 34.148 34.494
## -----------------------------------------------------------
## Total 7895 7816 15711
## ===========================================================
##
## Statistics for All Table Factors
##
## Pearson's Chi-squared test
## ------------------------------------------------------------
## Chi^2 = 414.4949 d.f. = 3 p <2e-16
##
## Minimum expected frequency: 376.5968
Contrairement à d’autres logiciels statistiques (SAS tout particulièrement), R ne possède pas une procédure permettant de calculer automatiquement l’ensemble des statistiques descriptives standards dans le cas d’une variable de nature quantitative, mais un ensemble de fonctions élémentaires (cf. tableau).
Code R | Résultat |
---|---|
sum(x) |
Somme de x |
mean(x) |
Moyenne de x |
var(x) |
Variance empirique de x |
sd(x) |
Écart-type empirique de x |
quantile(x) |
Quantiles de x |
summary(x) |
Moyenne et quantiles de x |
max(x) |
Valeur maximum de x |
min(x) |
Valeur minimum de x |
range(x) |
Valeur minimale et valeur maximale de x |
cor.test(x, y) |
Corrélation entre x et y |
En présence de valeurs manquantes (NA
), la plupart de ces fonctions renvoient la valeur NA
: l’argument na.rm = TRUE
permet de modifier ce comportement.
# Statistiques descriptives standards sur le salaire dans l'EEC
mean(eec$salred)
## [1] NA
# Il y a manifestement des valeurs manquantes
sum(is.na(eec$salred))
## [1] 19794
# Les valeurs manquantes correspondent à 19 794 observations
# sur 34 913, ce qui est logique : ni les inactifs ni les non-
# salariés ne touchent de salaire.
mean(eec$salred, na.rm = TRUE)
## [1] 1819.209
sd(eec$salred, na.rm = TRUE)
## [1] 1195.574
quantile(eec$salred, na.rm = TRUE)
## 0% 25% 50% 75% 100%
## 24 1219 1600 2158 30042
quantile(eec$salred, na.rm = TRUE, probs = c(0.01, 0.05, 0.95, 0.99))
## 1% 5% 95% 99%
## 180.00 500.00 3683.00 6113.94
range(eec$salred, na.rm = TRUE)
## [1] 24 30042
# Coefficients de corrélation
cor.test(eec$salred, as.numeric(eec$age), method = "pearson")
##
## Pearson's product-moment correlation
##
## data: eec$salred and as.numeric(eec$age)
## t = 21.844, df = 15117, p-value < 2.2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
## 0.1594280 0.1903331
## sample estimates:
## cor
## 0.1749237
cor.test(eec$salred, as.numeric(eec$age), method = "spearman")
## Warning in cor.test.default(eec$salred, as.numeric(eec$age), method =
## "spearman"): Cannot compute exact p-value with ties
##
## Spearman's rank correlation rho
##
## data: eec$salred and as.numeric(eec$age)
## S = 464970000000, p-value < 2.2e-16
## alternative hypothesis: true rho is not equal to 0
## sample estimates:
## rho
## 0.1927504
cor.test(eec$salred, as.numeric(eec$age), method = "kendall")
##
## Kendall's rank correlation tau
##
## data: eec$salred and as.numeric(eec$age)
## z = 24.949, p-value < 2.2e-16
## alternative hypothesis: true tau is not equal to 0
## sample estimates:
## tau
## 0.1371121
Comme dans le cas des variables qualitatives, par défaut R ne prend pas en charge le calcul de statistiques descriptives pondérées. C’est ce que fait en revanche le package Hmisc
, avec la série des fonctions wtd
: wtd.mean()
, wtd.var()
, wtd.quantile()
notamment, qui comportent un argument weights
.
# Installation du package Hmisc
# install.packages("Hmisc")
# Chargement du package Hmisc
library(Hmisc)
# Statistiques pondérées avec Hmisc
wtd.mean(eec$salred, weights = eec$extri1613)
## [1] 1833.879
sqrt(wtd.var(eec$salred, weights = eec$extri1613))
## [1] 1224.982
wtd.quantile(eec$salred, weights = eec$extri1613, probs = seq(0, 1, 0.05))
## 0% 5% 10% 15% 20% 25% 30% 35% 40% 45% 50% 55%
## 24 507 758 1000 1150 1233 1302 1400 1459 1517 1600 1700
## 60% 65% 70% 75% 80% 85% 90% 95% 100%
## 1800 1900 2000 2164 2332 2578 2984 3695 30042
# Note : les fonctions wtd. du package Hmisc disposent
# également d'un paramètres na.rm, mais sa valeur est TRUE
# par défaut.
La production de graphiques est relativement simple dans R : dans la plupart des cas, c’est la fonction plot()
qu’il convient d’utiliser, qui adapte automatiquement le graphique aux caractéristiques de l’objet représenté. De nombreuses options graphiques (taper ? plot
pour en afficher quelques unes) permettent de personnaliser assez finement l’affichage.
Pour représenter un nuage de points, il suffit par exemple d’appliquer plot()
aux deux variables à représenter.
# On se restreint à une sous-base pour ne pas avoir un
# nuage de points trop dense
eec8 <- eec[which(!is.na(eec$salred))[1:100], ]
eec8$age <- as.numeric(eec8$age)
# Représentation du salaire en fonction de l'âge
plot(eec8$age, eec8$salred)
Plusieurs options de base contrôlent l’affichage des titres et des axes :
main
: titre principal du graphique ;xlab
, ylab
: titres des axes ;xlim
, ylim
: vecteurs de longueur 2 indiquant les limites des axes des abscisses et des ordonnées respectivement.# Personnalisation du graphique précédent (1)
plot(
eec8$age, eec8$salred
, main = "Âge et salaire dans l'EEC 2012 T4"
, xlab = "Âge", ylab = "Salaire en euros"
, xlim= c(15, 75)
)
Les options pch
et col
permettent de modifier la forme et la couleur des points représentés.
# Personnalisation du graphique précédent (2)
plot(
eec8$age, eec8$salred
, main = "Âge et salaire dans l'EEC 2012 T4"
, xlab = "Âge", ylab = "Salaire en euros"
, xlim= c(15, 75)
, pch = 0, col = 2
)
Utilisées avec des vecteurs et la fonction legend()
, pch
et col
permettent de représenter le croisement de plusieurs variables.
# Utilisation de pch pour distinguer hommes et femmes
# sur le graphique
plot(
eec8$age, eec8$salred
, main = "Âge et salaire dans l'EEC 2012 T4"
, xlab = "Âge", ylab = "Salaire en euros"
, xlim= c(15, 75)
, pch = as.numeric(eec8$sexe == "2")
)
# Ajout d'une légende
legend("topright", legend=c("Hommes","Femmes"), pch=c(0, 1))
# Sauvegarde du graphique pour la suite
g1 <- recordPlot()
Les fonctions abline()
et curve()
ajoutent respectivement des lignes et des courbes à un graphique existant.
# Modèle de régression linéaire : salaire = age + sexe
# (cf. dernière partie)
eec8$femme <- eec8$sexe == "2"
m1 <- lm(salred ~ age + femme, data = eec8)
# Représentation des droites de régression correspondant
# aux hommes et aux femmes respectivement
g1
abline(a = coef(m1)[1], b = coef(m1)[2])
abline(a = coef(m1)[1] + coef(m1)[3], b = coef(m1)[2], lty = 2)
# Modèle de régression linéaire : salaire = age + age^2 + sexe
# (cf. sous-partie suivante)
eec8$age2 <- eec8$age^2
m2 <- lm(salred ~ age + age2 + femme, data = eec8)
# Représentation des courbes de régression correspondant
# aux hommes et aux femmes respectivement
g1
curve(coef(m2)[1] + coef(m2)[2]*x + coef(m2)[3]*x^2, add = TRUE)
curve(coef(m2)[1] + coef(m2)[4] + coef(m2)[2]*x + coef(m2)[3]*x^2, lty=2, add = TRUE)
La fonction plot()
permet également de représenter la fonction de répartition et la densité empirique d’une distribution, par le biais des fonctions ecdf()
et density()
.
# Fonction de répartition empirique du salaire
plot(
ecdf(eec$salred)
, main = "Fonction de répartition empirique du salaire"
)
# Densité empirique du salaire
plot(
density(eec$salred, na.rm = TRUE)
, main = "Densité empirique du salaire"
)
Au-delà de la fonction plot()
, de nombreuses fonctions permettent d’effectuer des représentations spécifiques dans R :
hist()
produit l’histogramme d’une distribution ;
# Histogramme du salaire dans l'EEC
hist(eec$salred, xlim = c(0, 4000), breaks = seq(0, 100000, 250))
barplot()
et pie()
produisent respectivement le diagramme en bâtons et le diagramme circulaire représentant la fréquence d’une variable qualitative.
# Distribution de la position du marché du travail
# en milliers
pos <- by(eec$extri1613, eec$acteu, sum) / 1000
# Diagramme en bâtons de la position sur le marché du travail
barplot(
pos
, names.arg = c("Actifs occupés", "Chômeurs", "Inactifs")
, main = "Position sur le marché du travail au 2012 T4 \n (en milliers)"
)
# Diagramme circulaire de la position sur le marché du travail
pie(
pos
, labels = paste0(c("Actifs occupés", "Chômeurs", "Inactifs"), " (", round(pos),")")
, main = "Position sur le marché du travail au 2012 T4 \n (en milliers)"
)
L’enquête Pisa () est une enquête réalisée tous les trois ans par l’Organisation de coopération et de développement économique (OCDE) dans une soixantaine de pays auprès des élèves de 15 ans (quelle que soit leur classe au moment de l’enquête).
Elle vise à mesurer les acquis des élèves de 15 ans dans trois disciplines : mathématiques, compréhension de l’écrit (ou littératie) et sciences. En plus des scores aux tests standardisés de mathématiques, compréhension de l’écrit et sciences, cette enquête comporte de très nombreuses informations sur l’origine sociale des élèves, leurs conditions d’enseignement ainsi que leur rapport aux enseignants et à l’école.
Organisation des fichiers Les fichiers de l’enquête Pisa 2012 et leur documentation sont librement téléchargeables sur le site de l’OCDE. Seuls deux des nombreux fichiers de données qui constituent l’enquête seront utilisés :
pisa_stu.sas7bdat
;pisa_sch.sas7bdat
.Ces deux fichiers ont été restreints à la France et à un ensemble réduit de variables:
Fichier élève (pisa_stu.sas7bdat
)
Variable | Description |
---|---|
cnt | Pays |
stidstd | Identifiant de l’élève |
schoolid | Identifiant de l’établissement |
w_fstuwt | Poids de sondage final de l’élève |
st01q01 | Classe en nombre d’années depuis l’entrée en primaire: la 10\(^{ème}\) classe correspond à la seconde en France. |
st04q01 | Sexe : (1) Femme (2) Homme |
st05q01 | A suivi une scolarité pré-primaire (1) Non (2) Oui, un an ou moins (3) Oui, plus d’un an |
st07q01 st07q02 st07q03 | A redoublé à un moment de sa scolarité : (1) Non (2-3) Oui, une ou plusieurs fois |
st08q01 | Est arrivé en retard au cours des deux semaines précédant l’enquête |
st09q01 | A séché les cours au cours des deux semaines précédant l’enquête |
anxmat | Score synthétique d’anxiété en mathématiques |
disclima | Score synthétique de climat de discipline dans la classe |
escs | Indicateur synthétique de statut économique, social et culturel |
immig | Immigration : (1) Né en France (2) Immigré de deuxième génération (3) Immigré de première génération |
hisced | Niveau d’étude le plus élevé des parents (nomenclature CITE) |
pv1math | Score synthétique à l’évaluation de mathématiques |
pv1read | Score synthétique à l’évaluation de compréhension de l’écrit |
pv1scie | Score synthétique à l’évaluation de sciences |
Fichier établissement (pisa_sch.sas7bdat
)
Variable | Description |
---|---|
cnt | Pays |
schoolid | Identifiant de l’établissement |
senwgt_scq | Poids de sondage (la somme vaut 1 000 dans chaque pays) |
sc01q01 | Statut public ou privé (1) public (2) privé |
sc03q01 | Taille de la commune de l’établissement : (1) Village (2) Small town (3) Town (4) City (5) Large city |
sc05q01 | Taille de la classe en cours de français : (01) 15 ou moins (02) 16-20 (03) 21-25 … (08) 46-50 (09) Plus de 50 élèves |
Utilisez la fonction read_sas()
du package haven
(cf. module 1) pour importer les deux fichiers dans les objets stu
et sch
respectivement. Afin de faciliter les exploitations futures, passez leurs noms de variables en minuscules.
On souhaite pouvoir utiliser les informations au niveau de l’établissement dans des exploitations au niveau des élèves. Pour ce faire, il convient de fusionner les tables stu
et sch
sur la base de la variable schoolid
.
Utilisez les fonctions unique()
, intersect()
et setdiff()
pour vérifier que l’identifiant schoolid
prend bien les mêmes valeurs dans les deux tables.
Vérifiez que la variable schoolid
est un identifiant pour la table sch
, à savoir : (1) qu’elle est renseignée pour chaque ligne (2) qu’elle prend une valeur distincte pour chaque ligne.
Utilisez la fonction merge()
pour fusionner stu
et sch
par schoolid
et créez la table stu2
. Vérifiez que ses propriétés sont cohérentes avec le résultat des questions précédentes : même nombre de lignes que stu
, nombre de colonnes égal à celui de stu
et de sch
moins 1.
Recodage de variables
Recodez la variable de sexe en facteur dont les libellés sont "Femme"
et "Homme"
pour faciliter la lecture des tableaux et graphiques.
Un élève a redoublé à un moment dans sa scolarité dès lors qu’une des variables st07q01
, st07q02
ou st07q03
vaut 2 ou 3. Créez la variable indicatrice redoublant
valant TRUE
si un élève a redoublé au cours de sa scolarité.
Quelle est la nature de l’indicateur synthétique de statut économique, social et culturel ? Recodez-le sous la forme d’une variable qualitative à 5 modalités (en utilisant les fonctions cut()
et quantile()
).
En utilisant le package descr
, effectuez le tri croisé entre sexe des élèves et redoublement et interprétez-le.
Calculez le coefficient de corrélation linéaire de Pearson entre notes en mathématiques et en sciences et menez le test de nullité de ce coefficient (avec la fonction cor.test()
).
Calculez le score moyen en mathématiques selon les quintiles de statut économique, social et culturel (cf. le recodage du cas pratique précédent).
Construisez un diagramme en bâton pour illustrer la relation entre statut économique, social et culturel (en quintiles) et redoublement. Utilisez les options de mise en forme pour améliorer sa présentation (ajouter un titre avec main()
, modifiez les titres des axes avec xlab()
et ylab()
, etc.).
Utilisez la fonction plot()
pour représenter le nuage de points de la relation entre le score en mathématiques et le score en sciences.
Construisez la “boîte à moustaches” représentant la relation entre stat au moinst économique, social et culturel (en quintiles) et score en mathématiques à l’aide de la fonction boxplot()
.
Utilisez les fonctionnalités de RStudio (menus déroulants de la fenêtre de graphiques) pour sauvegarder ces graphiques dans la qualité et le format souhaités.
Le support de la formation R perfectionnement est en ligne à l’adresse : t.slmc.fr/perf. Elle aborde trois sujets :
Outils et méthodes pour se perfectionner avec R ;
Traitements avancés sur des données dans R : retour sur les fonctions *apply()
et assimilées, optimisation en base R, packages dplyr
et data.table
, parallélisation et utilisation de langages de bas niveau dans R.
Graphiques et reporting avec R : package ggplot2
, production automatique de documents avec Rmarkdown.
Un cycle de formations perfectionnement est également proposé par la Division Formation : certaines portent sensiblement sur les mêmes sujets, mais pas toutes (notamment une consacrée à R Shiny).
Le package FactoMineR
(attention à la casse !) rend extrêmement simple la mise en oeuvre sous R de techniques d’analyse de données multidimensionnelles : analyse en composante principale (ACP), analyse des correspondances multiples (ACM) ou encore classification ascendante hiérarchique (CAH).
Ce document d’introduction (“vignette” dans la terminologie de R) présente ces méthodes et leur mise en oeuvre avec FactoMineR
.
Les fonctions natives de R lm()
et glm()
permettent respectivement d’estimer des modèles linéaires et linéaires généralisés (dont les modèles logistiques).
Cette page (destinée à un public de non-statisticiens) introduit les méthodes de régression et propose de nombreux exemples d’estimation de modèles dans R.