IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Cours complet pour apprendre R avec une pratique pour l'analyse de données sociologiques

Image non disponible R pour les sociologues (et assimilés)


précédentsommairesuivant

Partie 5 Manipulation de données

Cette partie est un peu aride et pas forcément très intuitive. Elle aborde cependant la base de tous les traitements et manipulations de données sous R, et mérite donc que l'on s'y arrête un moment, ou que l'on y revienne un peu plus tard en cas de saturation…

Variables

Le type d'objet utilisé par R pour stocker des tableaux de données s'appelle un data frame. Celui-ci comporte des observations en ligne et des variables en colonnes. On accède aux variables d'un data frame avec l'opérateur $.

Dans ce qui suit, on travaillera sur le jeu de données tiré de l'enquête Histoire de vie, fourni avec l'extension rgrs et décrit dans l'annexe B.3.3B.3.3 Le jeu de données hdv2003.

 
Sélectionnez
R> library(rgrs)
R> data(hdv2003)
R> d <- hdv2003

Mais aussi sur le jeu de données tiré du recensement 1999, décrit dans l'annexe B.3.4B.3.4 Le jeu de données rp99 :

 
Sélectionnez
R> data(rp99)

Types de variables

On peut considérer qu'il existe quatre types de variables dans R :

  • les variables numériques, ou quantitatives ;
  • les 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 ;
  • les variables 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 ;
  • les variables booléennes, qui ne peuvent prendre que la valeur vrai (TRUE) ou faux (FALSE). On les utilise dans R pour les calculs et les recodages.

Pour connaître le type d'une variable donnée, on peut utiliser la fonction class.

Résultat de class

Type de variable

factor

Facteur

integer

Numérique

double

Numérique

numeric

Numérique

character

Caractères

logical

Booléenne

 
Sélectionnez
1.
2.
3.
4.
5.
6.
R> class(d$age)
[1] "integer"
R> class(d$sexe)
[1] "factor"
R> class(c(TRUE, TRUE, FALSE))
[1] "logical"

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

Renommer des variables

Une opération courante lorsque l'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 seconde remarque de la section 2.2.1Objets simples.

On peut lister les noms des variables d'un data frame à l'aide de la fonction names :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
R> names(d)
 [1] "id"            "age"            "sexe"           "nivetud"
 [5] "poids"         "occup"          "qualif"         "freres.soeurs"
 [9] "clso"          "relig"          "trav.imp"       "trav.satisf"
[13] "hard.rock"     "lecture.bd"     "peche.chasse"   "cuisine"
[17] "bricol"        "cinema"         "sport"          "heures.tv"

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 :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
R> d.maj <- d
R> 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")
R> summary(d.maj$SEXE)
Homme Femme
  899  1101

Ce type de renommage peut être utile lorsque l'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 passionnant, on peut utiliser la fonction dput :

 
Sélectionnez
1.
2.
3.
4.
5.
R> dput(names(d))
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")

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 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 renomme.variable de l'extension rgrs. 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 bricol du tableau de données d en bricolage :

 
Sélectionnez
1.
2.
3.
4.
R> d <- renomme.variable(d, "bricol", "bricolage")
R> table(d$bricolage)
 Non  Oui
1147  853

Facteurs

Parmi les différents types de variables, les facteurs (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 levels :

 
Sélectionnez
1.
2.
R> levels(d$sexe)
[1] "Homme" "Femme"

Si on veut modifier la valeur du sexe du premier individu de notre tableau de données avec une valeur différente, on obtient un message d'erreur et une valeur manquante est utilisée à la place :

 
Sélectionnez
1.
2.
3.
4.
R> d$sexe[1] <- "Chihuahua"
R> d$sexe[1]
[1] <NA>
Levels: Homme Femme

On peut très facilement créer un facteur à partir d'une variable de type caractères avec la commande factor :

 
Sélectionnez
1.
2.
3.
4.
R> v <- factor(c("H", "H", "F", "H"))
R> v
[1] H H F H
Levels: F H

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. Cet ordre des niveaux est utilisé à chaque fois que l'on emploie des fonctions comme table, par exemple :

 
Sélectionnez
1.
2.
3.
4.
R> table(v)
v
F H
1 3

On peut modifier cet ordre au moment de la création du facteur en utilisant l'option levels :

 
Sélectionnez
1.
2.
3.
4.
5.
R> v <- factor(c("H", "H", "F", "H"), levels = c("H", "F"))
R> table(v)
v
H F
3 1

On peut aussi modifier l'ordre des niveaux d'une variable déjà existante :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
R> d$qualif <- factor(d$qualif, levels = c("Ouvrier specialise",
+     "Ouvrier qualifie", "Employe", "Technicien", "Profession intermediaire",
+     "Cadre", "Autre"))
R> table(d$qualif)
      Ouvrier specialise         Ouvrier qualifie               Employe
                     203                      292                   594
              Technicien Profession intermediaire                 Cadre
                      86                      160                   260
                   Autre
                      58

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 l'option exclude=NULL. Ceci signifie cependant qu'elles ne seront plus considérées comme manquantes par R :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
R> summary(d$trav.satisf)
  Satisfaction Insatisfaction      Equilibre           NA's
           480            117            451            952
R> summary(factor(d$trav.satisf, exclude = NULL))
 Satisfaction Insatisfaction       Equilibre           <NA>
          480            117             451            952

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.

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 :

 
Sélectionnez
R> v <- c("a", "b", "c", "d", "e", "f", "g")

Si on souhaite le premier élément du vecteur, on peut faire :

 
Sélectionnez
R> v[1]
[1] "a"

Si on souhaite les trois premiers éléments ou les éléments 2, 6 et 7 :

 
Sélectionnez
1.
2.
3.
4.
R> v[1:3]
[1] "a" "b" "c"
R> v[c(2, 6, 7)]
[1] "b" "f" "g"

Si on veut le dernier élément :

 
Sélectionnez
R> v[length(v)]
[1] "g"

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 lignes et le second les colonnes. Ainsi, si on veut l'élément correspondant à la troisième ligne et à la cinquième colonne du tableau de données d :

 
Sélectionnez
R> d[3, 5]
[1] 3994.102

On peut également indiquer des vecteurs :

 
Sélectionnez
1.
2.
3.
4.
5.
R> d[1:3, 1:2]
  id age
1  1  28
2  2  23
3  3  59

Si on laisse l'un des deux critères vide, 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 :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
R> d[, 5]
 [1] 2634.3982  9738.3958  3994.1025 5731.6615 4329.0940  8674.6994
 [7] 6165.8035 12891.6408  7808.8721 2277.1605  704.3227  6697.8682
[13] 7118.4659   586.7714 11042.0774 9958.2287 4836.1393  1551.4846
[19] 3141.1572 27195.8378 14647.9983 8128.0603 1281.9156 11663.3383
[25] 8780.2614  1700.8437  6662.8375 3359.4690 8536.1101 10620.5259
[31] 5264.2953 14161.7597  1339.6196 9243.9153 4512.2959  7871.6452
[37] 1356.9621  7626.3300  1630.2746 2196.2485 5605.9846  8841.2960
[43] 9113.5378  2267.5912  7706.2944 2446.5111 8118.2639 10751.5037
[49]  831.8599  6591.6440  1936.8826  834.3845 3432.5286 11354.8932
[55] 9292.9762  6344.1227  4899.9404 4766.8652 3462.8121 23732.4853
[61]  833.8428  8529.4403  3190.3680 2423.1052 5945.9929 14991.8652
[67] 2062.1124  5702.0623 20604.2642 2634.4861
 [ reached getOption("max.print") -- omitted 1930 entries ]]
R> d[1:2, ]
  id age  sexe nivetud
1  1  28 Femme Enseignement superieur y compris technique superieur
2  2  23 Femme                                                 <NA>
     poids                 occup  qualif freres.soeurs clso
1 2634.398 Exerce une profession Employe             8  Oui
2 9738.396       Etudiant, eleve    <NA>             2  Oui
                        relig      trav.imp    trav.satisf hard.rock
1 Ni croyance ni appartenance Peu important Insatisfaction       Non
2 Ni croyance ni appartenance         <NA>            <NA>       Non
  lecture.bd peche.chasse cuisine bricol cinema sport heures.tv
1        Non          Non     Oui    Non    Non   Non         0
2        Non          Non     Non    Non    Oui   Oui         1

Enfin, si on préfixe les arguments avec le signe « - », ceci signifie « tous les éléments sauf ceux indiqués ». Si, par exemple on veut tous les éléments de v sauf le premier :

 
Sélectionnez
R> v[-1]
[1] "b" "c" "d" "e" "f" "g"

Bien sûr, tous ces critères se combinent et on peut stocker le résultat dans un nouvel objet. Dans cet exemple d2 contiendra les trois premières lignes de d,mais sans les colonnes 2, 6 et 8.

 
Sélectionnez
R> d2 <- d[1:3, -c(2, 6, 8)]

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 :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
R> d$clso
 [1] Oui          Oui          Non          Non          Oui         
 [6] Non          Oui          Non          Oui          Non         
[11] Oui          Oui          Oui          Oui          Oui         
[16] Non          Non          Non          Non          Non         
[21] Oui          Oui          Non          Non          Non         
[26] Oui          Non          Non          Non          Oui         
[31] Non          Oui          Oui          Non          Non         
[36] Oui          Oui          Non          Non          Oui         
[41] Non          Non          Oui          Non          Non         
[46] Non          Non          Oui          Oui          Non         
[51] Non          Non          Oui          Non          Oui         
[56] Oui          Non          Non          Oui          Non         
[61] Non          Oui          Oui          Oui          Oui         
[66] Non          Oui          Non          Non          Ne sait pas
 [ reached getOption("max.print") -- omitted 1930 entries ]]
Levels: Oui Non Ne sait pas
R> d[, "clso"]
 [1] Oui          Oui          Non          Non          Oui         
 [6] Non          Oui          Non          Oui          Non         
[11] Oui          Oui          Oui          Oui          Oui         
[16] Non          Non          Non          Non          Non         
[21] Oui          Oui          Non          Non          Non         
[26] Oui          Non          Non          Non          Oui         
[31] Non          Oui          Oui          Non          Non         
[36] Oui          Oui          Non          Non          Oui         
[41] Non          Non          Oui          Non          Non         
[46] Non          Non          Oui          Oui          Non         
[51] Non          Non          Oui          Non          Oui         
[56] Oui          Non          Non          Oui          Non         
[61] Non          Oui          Oui          Oui          Oui         
[66] Non          Oui          Non          Non          Ne sait pas
 [ reached getOption("max.print") -- omitted 1930 entries ]]
Levels: Oui Non Ne sait pas

Là aussi on peut utiliser un vecteur pour sélectionner plusieurs noms et récupérer un « sous-tableau » de données :

 
Sélectionnez
R> 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 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 rp99 le nom des communes correspondantes :

 
Sélectionnez
R> row.names(rp99) <- rp99$nom

On peut alors accéder directement aux communes en donnant leur nom :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
R> rp99[c("VILLEURBANNE", "OULLINS"), ]
                      nom  code pop.act pop.tot  pop15 nb.rp      agric
VILLEURBANNE VILLEURBANNE 69266   57252  124152 103157 55136 0.02095997
OULLINS           OULLINS 69149   11849   25186  20880 11091 0.10127437
                artis   cadres   interm     empl     ouvr     retr
VILLEURBANNE 5.143925 13.13841 25.72312 31.41550 23.07343 36.65374
OULLINS      4.818972 10.20339 27.42847 31.53009 24.37336 41.54781
              tx.chom     etud dipl.sup dipl.aucun  proprio      hlm
VILLEURBANNE 14.82394 15.50646 9.744370   16.90045 37.61970 23.33684
OULLINS      10.64225 10.62739 7.624521   14.31513 51.51023 14.56136
            locataire    maison
VILLEURBANNE 32.76988  6.532937
OULLINS      29.91615 17.708052

Par contre, il n'est pas possible d'utiliser directement l'opérateur « - » comme pour l'indexation directe. On doit effectuer une pirouette un peu compliquée utilisant la fonction which. Celle-ci renvoie les positions des éléments satisfaisant une condition. On peut ainsi faire :

 
Sélectionnez
1.
2.
3.
R> which(names(d) == "qualif")
[1] 7
R> d2 <- d[, -which(names(d) == "qualif")]

pour sélectionner toutes les colonnes sauf celle qui s'appelle qualif.

Indexation par conditions

Tests et conditions

Une condition est une expression logique dont le résultat est soit TRUE (vrai) soit FALSE (faux).

Une condition comprend la plupart du temps un opérateur de comparaison. Les plus courants sont les suivants :

Opérateur

Signification

==

égal à

!=

différent de

>

strictement supérieur à

<

strictement inférieur à

>=

supérieur ou égal à

<=

inférieur ou égal à

Voyons tout de suite un exemple :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
R> d$sexe == "Homme"
 [1] FALSE FALSE  TRUE  TRUE FALSE FALSE FALSE  TRUE FALSE  TRUE FALSE
[12]  TRUE FALSE FALSE FALSE FALSE  TRUE FALSE  TRUE FALSE FALSE  TRUE
[23] FALSE FALSE FALSE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
[34]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE  TRUE  TRUE FALSE
[45] FALSE  TRUE FALSE FALSE FALSE FALSE  TRUE FALSE  TRUE FALSE  TRUE
[56] FALSE FALSE FALSE  TRUE FALSE FALSE  TRUE  TRUE  TRUE  TRUE FALSE
[67]  TRUE  TRUE FALSE FALSE
 [ reached getOption("max.print") -- omitted 1930 entries ]]

Que s'est-il passé ? Nous avons fourni à R une condition qui signifie « la valeur de la variable sexe vaut "Homme" ». Et il nous a renvoyé un vecteur avec autant d'éléments qu'il y a d'observations dans d, et dont la valeur est TRUE si l'observation correspond à un homme, et 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 head :

 
Sélectionnez
1.
2.
3.
4.
R> head(d$age)
[1] 28 23 59 34 71 35
R> head(d$age > 40)
[1] FALSE FALSE  TRUE FALSE  TRUE FALSE

On voit bien ici qu'à chaque élément du vecteur d$age dont la valeur est supérieure à 40 correspond un élément TRUE dans le résultat de la condition.

On peut combiner ou modifier des conditions à l'aide des opérateurs logiques habituels :

Opérateur

Signification

&

et logique

|

ou logique

!

négation logique

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 :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
R> d$sexe == "Homme" & d$qualif == "Ouvrier specialise"
 [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[12] FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE
[23] FALSE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE    NA
[34]    NA FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[45] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[56] FALSE FALSE FALSE FALSE FALSE FALSE    NA FALSE    NA FALSE FALSE
[67] FALSE FALSE FALSE FALSE
 [ reached getOption("max.print") -- omitted 1930 entries ]]

Si je souhaite identifier les personnes qui bricolent ou qui font la cuisine :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
R> d$bricol == "Oui" | d$cuisine == "Oui"
 [1]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE  TRUE FALSE FALSE  TRUE
[12]  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE FALSE FALSE  TRUE FALSE
[23]  TRUE FALSE  TRUE FALSE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE
[34]  TRUE  TRUE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE
[45] FALSE  TRUE  TRUE  TRUE FALSE FALSE  TRUE  TRUE FALSE FALSE FALSE
[56]  TRUE FALSE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE
[67]  TRUE  TRUE  TRUE  TRUE
 [ reached getOption("max.print") -- omitted 1930 entries ]]

Si je souhaite isoler les femmes qui ont entre 20 et 34 ans :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
R> d$sexe == "Femme" & d$age >= 20 & d$age <= 34
 [1]  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE
[12] FALSE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE
[23] FALSE FALSE  TRUE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE
[34] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[45] FALSE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE  TRUE FALSE
[56]  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE
[67] FALSE FALSE FALSE FALSE
 [ reached getOption("max.print") -- omitted 1930 entries ]]

Si je souhaite récupérer les enquêtés qui ne sont pas cadres, on peut utiliser l'une des deux formes suivantes :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
R> d$qualif != "Cadre"
 [1]  TRUE    NA  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE    NA  TRUE  TRUE
[12]  TRUE  TRUE    NA    NA  TRUE FALSE    NA  TRUE  TRUE  TRUE  TRUE
[23]  TRUE    NA  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE    NA
[34]    NA  TRUE  TRUE  TRUE    NA  TRUE FALSE  TRUE  TRUE FALSE FALSE
[45]    NA  TRUE  TRUE    NA  TRUE FALSE  TRUE  TRUE  TRUE    NA  TRUE
[56]  TRUE    NA FALSE  TRUE    NA  TRUE    NA  TRUE    NA  TRUE  TRUE
[67]  TRUE  TRUE  TRUE    NA
 [ reached getOption("max.print") -- omitted 1930 entries ]]
R> !(d$qualif == "Cadre")
 [1]  TRUE    NA  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE    NA  TRUE  TRUE
[12]  TRUE  TRUE    NA    NA  TRUE FALSE    NA  TRUE  TRUE  TRUE  TRUE
[23]  TRUE    NA  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE    NA
[34]    NA  TRUE  TRUE  TRUE    NA  TRUE FALSE  TRUE  TRUE FALSE FALSE
[45]    NA  TRUE  TRUE    NA  TRUE FALSE  TRUE  TRUE  TRUE    NA  TRUE
[56]  TRUE    NA FALSE  TRUE    NA  TRUE    NA  TRUE    NA  TRUE  TRUE
[67]  TRUE  TRUE  TRUE    NA
 [ reached getOption("max.print") -- omitted 1930 entries ]]

Lorsque l'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 cadres, soit employées :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
R> d$sexe == "Femme" & (d$qualif == "Employe" | d$qualif == "Cadre")
 [1]  TRUE    NA FALSE FALSE  TRUE  TRUE FALSE FALSE    NA FALSE  TRUE
[12] FALSE  TRUE    NA    NA  TRUE FALSE    NA FALSE FALSE  TRUE FALSE
[23]  TRUE    NA FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[34] FALSE FALSE  TRUE FALSE    NA  TRUE FALSE  TRUE FALSE FALSE  TRUE
[45]    NA FALSE FALSE    NA  TRUE  TRUE FALSE  TRUE FALSE    NA FALSE
[56] FALSE    NA  TRUE FALSE    NA  TRUE FALSE FALSE FALSE FALSE  TRUE
[67] FALSE FALSE  TRUE    NA
 [ reached getOption("max.print") -- omitted 1930 entries ]]

L'opérateur %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 :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
R> d$sexe == "Femme" & d$qualif %in% c("Employe", "Cadre")
 [1]  TRUE FALSE FALSE FALSE  TRUE  TRUE FALSE FALSE FALSE FALSE  TRUE
[12] FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE  TRUE FALSE
[23]  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[34] FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE  TRUE FALSE FALSE  TRUE
[45] FALSE FALSE FALSE FALSE  TRUE  TRUE FALSE  TRUE FALSE FALSE FALSE
[56] FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE  TRUE
[67] FALSE FALSE  TRUE FALSE
 [ reached getOption("max.print") -- omitted 1930 entries ]]

Enfin, signalons que l'on peut utiliser les fonctions table ou summary pour avoir une idée du résultat de notre condition :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
R> table(d$sexe)
Homme Femme
  899  1101
R> table(d$sexe == "Homme")
FALSE TRUE
 1101  899
R> summary(d$sexe == "Homme")
   Mode   FALSE    TRUE    NA's
logical    1101     899       0

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 à TRUE seront conservés.

Ainsi, si on fait :

 
Sélectionnez
R> dh <- d[d$sexe == "Homme", ]

on obtiendra un nouveau tableau de données comportant l'ensemble des variables de d, mais seulement les observations pour lesquelles 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 « a » ou « s » :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
R> d[, substr(names(d), 0, 1) %in% c("a", "s")]
    age  sexe sport
1    28 Femme  Non
2    23 Femme  Oui
3    59 Homme  Oui
4    34 Homme  Oui
5    71 Femme  Non
6    35 Femme  Oui
7    60 Femme  Non
8    47 Homme  Non
9    20 Femme  Non
10   28 Homme  Oui
11   65 Femme  Non
12   47 Homme  Oui
13   63 Femme  Non
14   67 Femme  Non
15   76 Femme  Non
16   49 Femme  Non
17   62 Homme  Oui
18   20 Femme  Oui
19   70 Homme  Non
20   39 Femme  Oui
21   30 Femme  Non
22   30 Homme  Non
23   37 Femme  Oui
 [getOption("max.print") est atteint -- 1977 lignes omises ]]

On peut évidemment combiner les différents types d'indexation. L'exemple suivant sélectionne les femmes de plus de 40 ans et ne conserve que les variables qualif et bricol.

 
Sélectionnez
R> d2 <- d[d$sexe == "Femme" & d$age > 40, c("qualif", "bricol")]

Valeurs manquantes dans les conditions

Une remarque importante : quand l'un des termes d'une condition comporte une valeur manquante (NA), le résultat de cette condition n'est pas toujours TRUE ou FALSE, il peut aussi être à son tour une valeur manquante.

 
Sélectionnez
1.
2.
3.
4.
5.
R> v <- c(1:5, NA)
R> v
[1] 1 2 3 4 5 NA
R> v > 3
[1] FALSE FALSE FALSE  TRUE  TRUE    NA

On voit que le test NA > 3 ne renvoie ni vrai ni faux, mais NA.

Le résultat d'une condition peut donc comporter un grand nombre de valeurs manquantes :

 
Sélectionnez
1.
2.
3.
R> summary(d$trav.satisf == "Satisfaction")
   Mode   FALSE   TRUE     NA's
logical     568    480      952

Une autre conséquence importante de ce comportement est que l'on ne peut pas utiliser l'opérateur == NA pour tester la présence de valeurs manquantes. On utilisera à la place la fonction ad hoc is.na.

On comprendra mieux le problème avec l'exemple suivant :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
R> v <- c(1, NA)
R> v
[1]  1 NA
R> v == NA
[1] NA NA
R> is.na(v)
[1] FALSE  TRUE

Pour compliquer encore un peu le tout, lorsque l'on utilise une condition pour l'indexation, si la condition renvoie NA, l'élément est sélectionné, comme s'il valait TRUE. Ceci aura donc des conséquences pour l'extraction de sous-populations, comme indiqué section 5.3.1Par indexation.

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

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

Ceci est parfaitement incompréhensible. Prenons donc un exemple simple :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
R> v <- 1:5
R> v
[1] 1 2 3 4 5
R> v[1] <- 3
R> v
[1] 3 2 3 4 5

Cette fois, au lieu d'utiliser quelque chose comme x <- v[1], qui aurait placé la valeur du premier élément de v dans x, on a utilisé v[1] <- 3, ce qui a mis à jour le premier élément de 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 :

 
Sélectionnez
R> 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 :

 
Sélectionnez
R> d[c(257, 438, 889), "sexe"] <- c("Homme", "Homme", "Homme")
R> 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.

 
Sélectionnez
R> d$age[d$age >= 20 & d$age <= 30] <- "20-30 ans"
R> d$age[is.na(d$age)] <- "Inconnu"

Sous-populations

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 :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
R> dh <- d[d$sexe == "Homme", ]
R> df <- d[d$sexe == "Femme", ]
R> table(d$sexe)
Homme Femme
  899  1101
R> dim(dh)
[1] 899 20
R> 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 :

 
Sélectionnez
1.
2.
3.
R> dh.25 <- d[d$sexe == "Homme" & d$age <= 25, ]
R> 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, l'existence d'une valeur manquante dans une condition fait que celle-ci est évaluée en NA et finalement sélectionnée par l'indexation :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
R> summary(d$trav.satisf)
Satisfaction Insatisfaction   Equilibre         NA's
         480            117         451          952
R> d.satisf <- d[d$trav.satisf == "Satisfaction", ]
R> 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 que l'on n'a pas de valeurs manquantes dans les variables de la condition, soit exclure explicitement les NA de la manière suivante :

 
Sélectionnez
1.
2.
3.
R> d.satisf <- d[d$trav.satisf == "Satisfaction" & !is.na(d$trav.satisf), ]
R> dim(d.satisf)
[1] 480  20

C'est notamment pour cette raison que l'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 :

 
Sélectionnez
R> dh <- subset(d, sexe == "Homme")
R> 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 :

 
Sélectionnez
R> dh <- subset(d, d$sexe == "Homme")
R> 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 :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
R> summary(d$trav.satisf)
 Satisfaction Insatisfaction     Equilibre          NA's
         480             117           451           952
R> d.satisf <- d[d$trav.satisf == "Satisfaction", ]
R> dim(d.satisf)
[1] 1432   20
R> d.satisf <- subset(d, trav.satisf == "Satisfaction")
R> dim(d.satisf)
[1] 480  20

Enfin, l'utilisation de l'argument select est simplifiée pour l'expression de condition sur les colonnes. On peut ainsi spécifier les noms de variables sans guillemets et leur appliquer directement l'opérateur d'exclusion - :

 
Sélectionnez
R> d2 <- subset(d, select = c(sexe, sport))
R> d2 <- subset(d, age > 25, select = -c(id, age, bricol))

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 !

 
Sélectionnez
R> 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 :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
R> tapply(d$bricol, d$sexe, freq)
$Homme
      n    %
Non 384 42.7
Oui 515 57.3
NA    0  0.0

$Femme
      n    %
Non 763 69.3
Oui 338 30.7
NA    0  0.0

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

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
R> tapply(d$bricol, d$sexe, freq, total = TRUE)
$Homme
        n     %
Non   384  42.7
Oui   515  57.3
NA      0   0.0
Total 899 100.0

$Femme
         n     %
Non    763  69.3
Oui    338  30.7
NA       0   0.0
Total 1101 100.0

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 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 Histoire de vie :

 
Sélectionnez
R> data(hdv2003)
R> d <- hdv2003

Convertir une variable

Il peut arriver que l'on veuille transformer une variable d'un type dans un autre.

Par exemple, on peut considérer que la variable numérique 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 factor :

 
Sélectionnez
1.
2.
3.
4.
R> d$fs.fac <- factor(d$freres.soeurs)
R> levels(d$fs.fac)
 [1] "0"  "1"  "2"  "3"  "4"  "5"  "6"  "7"  "8"  "9"  "10" "11" "12" "13"
[15] "14" "15" "16" "18" "22"

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 as.character :

 
Sélectionnez
1.
2.
R> d$fs.char <- as.character(d$freres.soeurs)
R> d$qualif.char <- as.character(d$qualif)

La conversion d'un facteur en caractères est fréquemment utilisée lors des recodages du fait qu'il est impossible d'ajouter de nouvelles modalités à un facteur. Par exemple, la première des commandes suivantes génère un message d'avertissement, tandis que les deux autres fonctionnent :

 
Sélectionnez
1.
2.
3.
R> d$qualif[d$qualif == "Ouvrier specialise"] <- "Ouvrier"
R> d$qualif.char <- as.character(d$qualif)
R> 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 qualif ont été remplacées par des valeurs manquantes NA.

Enfin, une variable de type caractères dont les valeurs seraient des nombres peut être convertie en variable numérique avec la fonction as.numeric. Si on souhaite convertir un facteur en variable numérique, il faut d'abord le convertir en variable de classe caractère :

 
Sélectionnez
R> d$fs.num <- as.numeric(as.character(d$fs.fac))

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

Celle-ci prend, outre la variable à découper, un certain nombre d'arguments :

  • breaks indique soit le nombre de classes souhaité, soit, si on lui fournit un vecteur, les limites des classes ;
  • labels permet de modifier les noms de modalités attribués aux classes ;
  • include.lowest et right influent sur la manière dont les valeurs situées à la frontière des classes seront incluses ou exclues ;
  • dig.lab indique le nombre de chiffres après la virgule à conserver dans les noms de modalités.

Prenons tout de suite un exemple et tentons de découper notre variable age en cinq classes et de placer le résultat dans une nouvelle variable nommée age5cl :

 
Sélectionnez
1.
2.
3.
4.
R> d$age5cl <- cut(d$age, 5)
R> table(d$age5cl)
(17.9,33.8] (33.8,49.6] (49.6,65.4] (65.4,81.2] (81.2,97.1]
        454         628         556         319          43

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 :

 
Sélectionnez
1.
2.
3.
4.
R> d$age20 <- cut(d$age, c(0, 20, 40, 60, 80, 100))
R> table(d$age20)
(0,20] (20,40] (40,60] (60,80] (80,100]
    72     660     780     436       52

On aurait pu tenir compte des âges extrêmes pour la première et la dernière valeur :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
R> range(d$age)
[1] 18 97
R> d$age20 <- cut(d$age, c(17, 20, 40, 60, 80, 93))
R> table(d$age20)
(17,20] (20,40] (40,60] (60,80] (80,93]
     72     660     780     436      50

Les symboles dans les noms attribués aux classes ont leur importance : ( signifie que la frontière de la classe est exclue, tandis que [ signifie qu'elle est incluse. Ainsi, (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 include.lowest=TRUE :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
R> d$age20 <- cut(d$age, c(16, 20, 40, 60, 80, 93))
R> table(d$age20)
(16,20] (20,40] (40,60] (60,80] (80,93]
    72      660     780     436      50
R> d$age20 <- cut(d$age, c(17, 20, 40, 60, 80, 93), include.lowest = TRUE)
R> table(d$age20)
[17,20] (20,40] (40,60] (60,80] (80,93]
     72     660     780     436      50

On peut également modifier le sens des intervalles avec l'option right=FALSE, et indiquer manuellement les noms des modalités avec labels :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
R> d$age20 <- cut(d$age, c(16, 20, 40, 60, 80, 93), right = FALSE, include.lowest = TRUE)
R> table(d$age20)
[16,20) [20,40) [40,60) [60,80) [80,93]
     48     643     793     454      60
R> d$age20 <- cut(d$age, c(17, 20, 40, 60, 80, 93), include.lowest = TRUE,
+     labels = c("<20 ans", "21-40 ans", "41-60 ans", "61-80 ans", ">80 ans"))
R> table(d$age20)
<20 ans 21-40 ans 41-60 ans 61-80 ans >80 ans
     72       660       780       436      50

Enfin, l'extension rgrs propose une fonction quant.cut permettant de découper une variable numérique en un nombre de classes donné ayant des effectifs semblables. Il suffit de lui passer le nombre de classes en argument :

 
Sélectionnez
1.
2.
3.
4.
R> d$age6cl <- quant.cut(d$age, 6)
R> table(d$age6cl)
[18,30) [30,39) [39,48) [48,55.667) [55.667,66) [66,97]
    302     337     350         344         305     362

quant.cut admet les mêmes autres options que cut (include.lowest, right, labels...).

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 qualif dans une variable qualif.reg plus « compacte », on peut utiliser :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
R> table(d$qualif)
       Ouvrier specialise,         Ouvrier qualifie,               Technicien
                      203,                      292,                       86
 Profession intermediaire,                    Cadre,                  Employe
                      160,                      260,                      594
                    Autre
                       58
R> d$qualif.reg[d$qualif == "Ouvrier specialise"] <- "Ouvrier"
R> d$qualif.reg[d$qualif == "Ouvrier qualifie"] <- "Ouvrier"
R> d$qualif.reg[d$qualif == "Employe"] <- "Employe"
R> d$qualif.reg[d$qualif == "Profession intermediaire"] <- "Intermediaire"
R> d$qualif.reg[d$qualif == "Technicien"] <- "Intermediaire"
R> d$qualif.reg[d$qualif == "Cadre"] <- "Cadre"
R> d$qualif.reg[d$qualif == "Autre"] <- "Autre"
R> table(d$qualif.reg)
         Autre         Cadre       Employe Intermediaire       Ouvrier
            58           260           594           246           495

On aurait pu représenter ce recodage de manière plus compacte, notamment en commençant par copier le contenu de qualif dans 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 qualif sous forme de facteur, sinon on ne pourrait ajouter de nouvelles modalités. On copie donc la version caractères de qualif grâce à la fonction as.character :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
R> d$qualif.reg <- as.character(d$qualif)
R> d$qualif.reg[d$qualif == "Ouvrier specialise"] <- "Ouvrier"
R> d$qualif.reg[d$qualif == "Ouvrier qualifie"] <- "Ouvrier"
R> d$qualif.reg[d$qualif == "Profession intermediaire"] <- "Intermediaire"
R> d$qualif.reg[d$qualif == "Technicien"] <- "Intermediaire"
R> table(d$qualif.reg)
         Autre         Cadre       Employe Intermediaire       Ouvrier
            58           260           594           246           495

On peut faire une version encore plus compacte en utilisant l'opérateur logique ou (|) :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
R> d$qualif.reg <- as.character(d$qualif)
R> d$qualif.reg[d$qualif == "Ouvrier specialise" | d$qualif == "Ouvrier qualifie"] <- "Ouvrier"
R> d$qualif.reg[d$qualif == "Profession intermediaire" | d$qualif == "Technicien"] <- "Intermediaire"
R> table(d$qualif.reg)
         Autre         Cadre       Employe Intermediaire       Ouvrier
            58           260           594           246           495

Enfin, pour terminer ce petit tour d'horizon, on peut également remplacer l'opérateur | par %in%, qui peut parfois être plus lisible :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
R> d$qualif.reg <- as.character(d$qualif)
R> d$qualif.reg[d$qualif %in% c("Ouvrier specialise", "Ouvrier qualifie")] <- "Ouvrier"
R> d$qualif.reg[d$qualif %in% c("Profession intermediaire", "Technicien")] <- "Intermediaire"
R> table(d$qualif.reg)
         Autre         Cadre       Employe Intermediaire       Ouvrier
            58           260           594           246           495

Dans tous les cas le résultat obtenu est une variable de type caractère. On pourra la convertir en facteur par un simple :

 
Sélectionnez
R> d$qualif.reg <- factor(d$qualif.reg)

Si on souhaite recoder les valeurs manquantes, il suffit de faire appel à la fonction is.na :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
R> table(d$trav.satisf)
  Satisfaction,Insatisfaction,     Equilibre
           480,           117,           451
R> d$trav.satisf.reg <- as.character(d$trav.satisf)
R> d$trav.satisf.reg[is.na(d$trav.satisf)] <- "Valeur manquante"
R> table(d$trav.satisf.reg)
        Equilibre   Insatisfaction     Satisfaction Valeur manquante
              451              117              480              952

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 :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
R> range(d$heures.tv, na.rm = TRUE)
[1] 0 12
R> mean(d$heures.tv, na.rm = TRUE)
[1] 2.246566
R> d$ecart.heures.tv <- d$heures.tv - mean(d$heures.tv, na.rm = TRUE)
R> range(d$ecart.heures.tv, na.rm = TRUE)
[1] -2.246566 9.753434
R> mean(d$ecart.heures.tv, na.rm = TRUE)
[1] 4.714578e-17

Autre exemple tiré du jeu de données rp99 : si on souhaite calculer le pourcentage d'actifs dans chaque commune, on peut diviser la population active pop.act par la population totale pop.tot.

 
Sélectionnez
R> rp99$part.actifs <- rp99$pop.act/rp99$pop.tot * 100

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 :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
R> d$act.manuelles <- NA
R> d$act.manuelles[d$cuisine == "Oui" & d$bricol == "Oui"] <- "Cuisine et Bricolage"
R> d$act.manuelles[d$cuisine == "Oui" & d$bricol == "Non"] <- "Cuisine seulement"
R> d$act.manuelles[d$cuisine == "Non" & d$bricol == "Oui"] <- "Bricolage seulement"
R> d$act.manuelles[d$cuisine == "Non" & d$bricol == "Non"] <- "Ni cuisine ni bricolage"
R> table(d$act.manuelles)
    Bricolage seulement   Cuisine et Bricolage      Cuisine seulement
                    437                    416                    465
Ni cuisine ni bricolage
                    682

On peut également combiner variables qualitatives et variables quantitatives :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
R> d$age.sexe <- NA
R> d$age.sexe[d$sexe == "Homme" & d$age < 40] <- "Homme moins de 40 ans"
R> d$age.sexe[d$sexe == "Homme" & d$age >= 40] <- "Homme plus de 40 ans"
R> d$age.sexe[d$sexe == "Femme" & d$age < 40] <- "Femme moins de 40 ans"
R> d$age.sexe[d$sexe == "Femme" & d$age >= 40] <- "Femme plus de 40 ans"
R> table(d$age.sexe)
 Femme moins de 40 ans   Femme plus de 40 ans  Homme moins de 40 ans
                   376                    725                    315
  Homme plus de 40 ans
                   584

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.

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 :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
R> d$score.ext <- 0
R> d$score.ext[d$cinema == "Oui"] <- d$score.ext[d$cinema == "Oui"] + 10
R> d$score.ext[d$peche.chasse == "Oui"] <- d$score.ext[d$peche.chasse == "Oui"] + 30
R> d$score.ext[d$sport == "Oui"] <- d$score.ext[d$sport == "Oui"] + 20
R> table(d$score.ext)
  0  10  20  30  40  50  60
800 342 229 509  31  41  48

Cette notation étant un peu lourde, on peut l'alléger un peu en utilisant la fonction 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.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
R> d$score.ext <- 0
R> d$score.ext <- ifelse(d$cinema == "Oui", 10, 0) + ifelse(d$peche.chasse ==
+ "Oui", 30, 0) + ifelse(d$sport == "Oui", 20, 0)
R> table(d$score.ext)
  0  10  20  30  40  50  60
800 342 229 509  31  41  48

Vérification des recodages

Il est très important de vérifier, notamment après les recodages les plus complexes, que l'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 table, et de vérifier le nombre de valeurs manquantes dans la variable recodée avec summary, freq ou table.

Par exemple :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
R> d$act.manuelles <- NA
R> d$act.manuelles[d$cuisine == "Oui" & d$bricol == "Oui"] <- "Cuisine et Bricolage"
R> d$act.manuelles[d$cuisine == "Oui" & d$bricol == "Non"] <- "Cuisine seulement"
R> d$act.manuelles[d$cuisine == "Non" & d$bricol == "Oui"] <- "Bricolage seulement"
R> d$act.manuelles[d$cuisine == "Non" & d$bricol == "Non"] <- "Ni cuisine ni bricolage"
R> table(d$act.manuelles, d$cuisine)
                        Non Oui
Bricolage seulement     437   0
Cuisine et Bricolage      0 416
Cuisine seulement         0 465
Ni cuisine ni bricolage 682   0
R> table(d$act.manuelles, d$bricol)
                        Non Oui
Bricolage seulement       0 437
Cuisine et Bricolage      0 416
Cuisine seulement       465   0
Ni cuisine ni bricolage 682   0

Tri de tables

On a déjà évoqué l'existence de la fonction sort, qui permet de trier les éléments d'un vecteur.

 
Sélectionnez
R> sort(c(2, 5, 6, 1, 8))
[1] 1 2 5 6 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 order. Celle-ci ne renvoie pas les valeurs du vecteur triées, mais les emplacements de ces valeurs.

Un exemple pour comprendre :

 
Sélectionnez
R> order(c(15, 20, 10))
[1] 3 1 2

Le résultat renvoyé signifie que la plus petite valeur est la valeur située en 3e position, suivie de celle en 1re position et de celle en 2e 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…

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
R> order(d$age)
 [1]  162  215  346  377  511  646  852  916 1211 1213 1261 1333 1395 1447
[15] 1600 1774 1937   38  100  134  196  204  256  257  349  395  407  427
[29]  453  578  726  969 1052 1056 1077 1177 1234 1250 1342 1377 1381 1382
[43] 1540 1559 1607 1634 1689 1983    9   18   25  231  335  347  358  488
[57]  496  642  826  922 1023 1042 1156 1175 1290 1384 1464 1467 1608 1661
 [ reached getOption("max.print") -- omitted 1930 entries ]]

Ce que cette fonction renvoie, c'est l'ordre dans lequel on doit placer les éléments de age, et donc par extension les lignes de d, pour que la variable soit triée par ordre croissant. Par conséquent, si on fait :

 
Sélectionnez
R> d.tri <- d[order(d$age), ]

alors on a trié les lignes de d par ordre d'âge croissant ! Et si on fait un petit :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
R> head(d.tri, 3)
     id age  sexe nivetud    poids           occup qualif freres.soeurs
162 162  18 Homme    <NA> 4982.964 Etudiant, eleve   <NA>             2
215 215  18 Homme    <NA> 4631.188 Etudiant, eleve   <NA>             2
    clso                       relig trav.imp trav.satisf hard.rock
162  Non  Appartenance sans pratique     <NA>        <NA>       Non
215  Oui Ni croyance ni appartenance     <NA>        <NA>       Non
    lecture.bd peche.chasse cuisine bricol cinema sport heures.tv fs.fac
162        Non          Non     Non    Non    Non   Oui         3      2
215        Non          Non     Oui    Non    Oui   Oui         2      2
    fs.char qualif.char fs.num      age5cl  age20  age6cl qualif.reg
162       2        <NA>      2 (17.9,33.8] <20ans [18,30)       <NA>
215       2        <NA>      2 (17.9,33.8] <20ans [18,30)       <NA>
     trav.satisf.reg ecart.heures.tv           act.manuelles
162 Valeur manquante       0.7534336 Ni cuisine ni bricolage
215 Valeur manquante      -0.2465664       Cuisine seulement
                 age.sexe score.ext
162 Homme moins de 40 ans        20
215 Homme moins de 40 ans        30
[getOption("max.print") est atteint -- dernière ligne omises ]]

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 decreasing=TRUE. On peut donc afficher les caractéristiques des trois individus les plus âgés avec :

 
Sélectionnez
R> head(d[order(d$age, decreasing = TRUE), ], 3)

Fusion de tables

Lorsque l'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 dbf ou Excel limités à 256 colonnes, par exemple).

Une opération relativement courante consiste à 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 Histoire de vie :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
R> data(hdv2003)
R> d <- hdv2003
R> dim(d)
[1] 2000   20
R> d1 <- subset(d, select = c("id", "age", "sexe"))
R> dim(d1)
[1] 2000    3
R> d2 <- subset(d, select = c("id", "clso"))
R> dim(d2)
[1] 2000    2

On a donc deux tableaux de données, d1 et 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 » d2 à la droite de d1, comme dans l'exemple suivant.

Image non disponible

Cela semble fonctionner. La fonction qui permet d'effectuer cette opération sous R s'appelle cbind, elle « colle » des tableaux côte à côte en regroupant leurs colonnes(18).

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
R> cbind(d1, d2)
     id   age  sexe    id  clso
1     1    28 Femme     1   Oui
2     2    23 Femme     2   Oui
3     3    59 Homme     3   Non
4     4    34 Homme     4   Non
5     5    71 Femme     5   Oui
6     6    35 Femme     6   Non
7     7    60 Femme     7   Oui
8     8    47 Homme     8   Non
9     9    20 Femme     9   Oui
10    10    28 Homme    10   Non
11    11    65 Femme    11   Oui
12    12    47 Homme    12   Oui
13    13    63 Femme    13   Oui
14    14    67 Femme    14   Oui
 [getOption("max.print") est atteint -- 1986 lignes omises ]]

À part le fait que l'on a une colonne id en double, le résultat semble satisfaisant. À première vue seulement. Imaginons maintenant que nous avons travaillé sur d1 et d2, et que nous avons ordonné les lignes de d1 selon l'âge des enquêtés :

 
Sélectionnez
R> d1 <- d1[order(d1$age), ]

Répétons l'opération de collage :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
R> cbind(d1, d2)
        id   age  sexe    id  clso
 162   162    18 Homme     1   Oui
 215   215    18 Homme     2   Oui
 346   346    18 Femme     3   Non
 377   377    18 Homme     4   Non
 511   511    18 Homme     5   Oui
 646   646    18 Homme     6   Non
 852   852    18 Femme     7   Oui
 916   916    18 Femme     8   Non
1211  1211    18 Homme     9   Oui
1213  1213    18 Femme    10   Non
1261  1261    18 Homme    11   Oui
1333  1333    18 Femme    12   Oui
1395  1395    18 Homme    13   Oui
1447  1447    18 Femme    14   Oui
 [getOption("max.print") est atteint -- 1986 lignes omises ]]

Que constate-t-on ? La présence de la variable 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 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 procéder à une 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 id.

Une fois l'identifiant reconnu(19), on peut utiliser la commande merge. Celle-ci va fusionner les deux tableaux en supprimant les colonnes en double et en regroupant les lignes selon leurs identifiants :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
R> d.complet <- merge(d1, d2, by = "id")
R> d.complet
         id   age  sexe  clso
    1     1    28 Femme   Oui
    2     2    23 Femme   Oui
    3     3    59 Homme   Non
    4     4    34 Homme   Non
    5     5    71 Femme   Oui
    6     6    35 Femme   Non
    7     7    60 Femme   Oui
    8     8    47 Homme   Non
    9     9    20 Femme   Oui
   10    10    28 Homme   Non
   11    11    65 Femme   Oui
   12    12    47 Homme   Oui
   13    13    63 Femme   Oui
   14    14    67 Femme   Oui
   15    15    76 Femme   Oui
   16    16    49 Femme   Non
   17    17    62 Homme   Non
 [getOption("max.print") est atteint -- 1983 lignes omises ]]

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 reconnu. Parfois les choses peuvent être un peu plus compliquées :

  • parfois les identifiants n'ont pas le même nom dans les deux tableaux. On peut alors les spécifier par les options by.x et by.y ;
  • parfois les deux tableaux comportent des colonnes (hors identifiants) ayant le même nom. merge conserve dans ce cas ces deux colonnes, mais les renomme en les suffixant par .x, pour celles provenant du premier tableau et .y pour celles du second ;
  • 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 by, par exemple by=c("nom","prenom","date.naissance").

Une subtilité supplémentaire intervient lorsque les deux tableaux fusionnés n'ont pas exactement les mêmes lignes. Par défaut, merge ne conserve que les lignes présentes dans les deux tableaux :

Image non disponible

On peut cependant modifier ce comportement avec les options all.x=TRUE et all.y=TRUE. La première option indique de conserver toutes les lignes du premier tableau. Dans ce cas merge donne une valeur NA pour ces lignes aux colonnes provenant du second tableau. Ce qui donnerait :

Image non disponible

all.y fait la même chose en conservant toutes les lignes du second tableau. On peut enfin décider de conserver toutes les lignes des deux tableaux en utilisant à la fois all.x=TRUE et all.y=TRUE, ce qui donne :

Image non disponible

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

Image non disponible

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 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, par définir le répertoire de travail à l'aide de setwd, à importer les données, à effectuer manipulations, traitements et recodages, puis à mettre en œuvre les analyses. Prenons le fichier fictif suivant :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
library(rgrs)
library(foreign)

setwd("/home/julien/r/projet")

## IMPORT DES DONNÉES

d1 <- read.dbf("tab1.dbf")
d2 <- read.dbf("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(20) 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é import.R dans notre répertoire de travail et copions les lignes suivantes :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
## IMPORT DES DONNÉES

d1 <- read.dbf("tab1.dbf")
d2 <- read.dbf("tab2.dbf")

d <- merge(d1, d2, by="id")

Créons également un fichier recodages.R avec le contenu suivant :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
## 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 source qui vont bien, le fichier suivant sera strictement équivalent à notre fichier de départ :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
library(rgrs)
library(foreign)

setwd("/home/julien/r/projet")

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

Cette méthode présente plusieurs avantages :

  • bien souvent, lorsque l'on effectue des recodages on se retrouve avec des variables recodées que l'on ne souhaite pas conserver. Si on prend l'habitude de placer les recodages intéressants dans le fichier recodages.R, alors il suffit d'exécuter les cinq premières lignes du fichier pour se retrouver avec un tableau de données d propre et complet ;
  • 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.

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 que l'on recommence à travailler. Ceci offre une traçabilité parfaite du traitement effectué sur les données.

Exercices

Exercice 5.11

? Solution

Renommer la variable clso du jeu de données hdv2003 en classes.sociales, puis la renommer en clso.

Exercice 5.12

? Solution

Réordonner les niveaux du facteur clso pour que son tri à plat s'affiche de la manière suivante :

 
Sélectionnez
tmp
            Non Ne sait pas         Oui
           1037          27         936

Exercice 5.13

? Solution

Affichez :

  • les 3 premiers éléments de la variable cinema ;
  • les éléments 12 à 30 de la variable lecture.bd ;
  • les colonnes 4 et 8 des lignes 5 et 12 du jeu de données hdv2003 ;
  • les 4 derniers éléments de la variable age.

Exercice 5.14

? Solution

Construisez les sous-tableaux suivants avec la fonction subset :

  • âge et sexe des lecteurs de BD ;
  • ensemble des personnes n'étant pas chômeur (variable occup), sans la variable cinema ;
  • identifiants des personnes de plus de 45 ans écoutant du hard rock ;
  • femmes entre 25 et 40 ans n'ayant pas fait de sport dans les douze derniers mois ;
  • hommes ayant entre 2 et 4 frères et sœurs et faisant la cuisine ou du bricolage.

Exercice 5.15

? Solution

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

Exercice 5.16

? Solution

Convertissez la variable 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.

Exercice 5.17

? Solution

Découpez la variable freres.soeurs :

  • en cinq classes d'amplitude égale ;
  • en catégories « de 0 à 2 », « de 3 à 4 », « plus de 4 », avec les étiquettes correspondantes ;
  • en quatre classes d'effectif équivalent ;
  • d'où vient la différence d'effectifs entre les deux découpages précédents ?

Exercice 5.18

? Solution

Recodez la variable trav.imp en 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 relig en 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é.

Exercice 5.19

? Solutionn

Créez une variable ayant les modalités suivantes :

  • homme de plus de 40 ans lecteur de BD ;
  • homme de plus de 30 ans ;
  • femme faisant du bricolage ;
  • autre.

Vérifier avec des tris croisés.

Exercice 5.20

? Solution

Ordonner le tableau de données selon le nombre de frères et sœurs croissant. Afficher le sexe des 10 individus regardant le plus la télévision.


précédentsommairesuivant
L'équivalent de cbind pour les lignes s'appelle rbind.
Si vous me passez l'expression…
Ceci n'est qu'une suggestion, la manière d'organiser (ou non) son travail étant bien évidemment très hautement subjectif.

Copyright © 2017 - Julien Barnier. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts