Dans ce qui suit on travaillera sur le jeu de données tiré de l’enquête Histoire de vie, fourni avec l’extension questionr.

library(questionr)
data(hdv2003)
d <- hdv2003

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 l’on souhaite isoler les hommes et les femmes :

dh <- d[d$sexe == "Homme", ]
df <- d[d$sexe == "Femme", ]
table(d$sexe)

Homme Femme 
  899  1101 
dim(dh)
[1] 899  20
dim(df)
[1] 1101   20

On a à partir de là trois tableaux de données, d comportant la population totale, dh seulement les hommes et df seulement les femmes.

On peut évidemment combiner plusieurs critères :

dh.25 <- d[d$sexe == "Homme" & d$age <= 25, ]
dim(dh.25)
[1] 86 20

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 NA et qu’au final la ligne correspondante est conservée par l’indexation :

summary(d$trav.satisf)
  Satisfaction Insatisfaction      Equilibre           NA's 
           480            117            451            952 
d.satisf <- d[d$trav.satisf == "Satisfaction", ]
dim(d.satisf)
[1] 1432   20

Comme on le voit, ici d.satisf contient les individus ayant la modalité Satisfaction mais aussi ceux ayant une valeur manquante 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 NA de la manière suivante :

d.satisf <- d[d$trav.satisf == "Satisfaction" & !is.na(d$trav.satisf), ]
dim(d.satisf)
[1] 480  20

C’est notamment pour cette raison qu’on préfèrera le plus souvent utiliser la fonction subset.

Fonction subset

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

  • le nom de l’objet de départ ;
  • une condition sur les observations (subset) ;
  • éventuellement une condition sur les colonnes (select).

Reprenons tout de suite un exemple déjà vu :

dh <- subset(d, sexe == "Homme")
df <- subset(d, sexe == "Femme")

L’utilisation de 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 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)
  Satisfaction Insatisfaction      Equilibre           NA's 
           480            117            451            952 
d.satisf <- d[d$trav.satisf == "Satisfaction", ]
dim(d.satisf)
[1] 1432   20
d.satisf <- subset(d, trav.satisf == "Satisfaction")
dim(d.satisf)
[1] 480  20

Dans le cas présent, l’extraction obtenue avec subset est équivalente à :

d.satisf <- d[d$trav.satisf == "Satisfaction" & !is.na(d$trav.satisf), ]
dim(d.satisf)
[1] 480  20

Enfin, l’utilisation de l’argument 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 - :

d2 <- subset(d, select = c(sexe, sport))
d2 <- subset(d, age > 25, select = -c(id, age, cinema))

Fonction tapply

Cette section documente une fonction qui peut être très utile, mais pas forcément indispensable au départ.

La fonction 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)
   Homme    Femme 
48.16129 48.15350 

Qu’est-ce que ça signifie ? Ici tapply a sélectionné toutes les observations correspondant à « Homme », puis appliqué la fonction mean aux valeurs de 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 à tapply :

tapply(d$bricol, d$sexe, freq)
$Homme
      n    % val%
Non 384 42.7 42.7
Oui 515 57.3 57.3

$Femme
      n    % val%
Non 763 69.3 69.3
Oui 338 30.7 30.7

Les arguments supplémentaires fournis à tapply sont en fait fournis directement à la fonction appelée.

tapply(d$bricol, d$sexe, freq, total = TRUE)
$Homme
        n     %  val%
Non   384  42.7  42.7
Oui   515  57.3  57.3
Total 899 100.0 100.0

$Femme
         n     %  val%
Non    763  69.3  69.3
Oui    338  30.7  30.7
Total 1101 100.0 100.0

La fonction by est un équivalent (pour les tableaux de données) de tapply. La présentation des résultats diffère légèrement.

tapply(d$age, d$sexe, mean)
   Homme    Femme 
48.16129 48.15350 
by(d$age, d$sexe, mean)
d$sexe: Homme
[1] 48.16129
--------------------------------------------- 
d$sexe: Femme
[1] 48.1535

Extension dplyr

On utilisera tout simplement la fonction filter.

library(dplyr)
tbl <- as_tibble(hdv2003)
hommes_jeunes <- tbl %>% filter(sexe == "Homme", age < 30)

Voir le chapitre dédié à dplyr pour plus de détails.

Extension data.table

Il suffit d’indiquer la condition entre crochets.

library(data.table)
dt <- as.data.table(hdv2003)
hommes_jeunes <- dt[sexe == "Hommes" & age < 30]

Il est également possible d’utiliser la fonction subset sur un data.table.

hommes_jeunes <- subset(dt, sexe == "Hommes" & age < 30)

Voir le chapitre dédié à data.table pour plus de détails.