> langage et graphiques > Arrays listes et dataframes > Dataframes avancés
Dataframes avancés
Sélection de lignes ou colonnes d'un dataframe :
- subset(fr, nom == "jean") : sélectione le sous dataframe en retenant les lignes dont la colonne nom vaut "jean" (ca peut être une expression plus complexe comme subset(fr, nom %in% c("pierre", "jean"))
- fr[which(fr$nom == "jean"), ] : autre façon de faire la même sélection.
- fr[fr$nom == "jean", ] : encore une autre façon de faire la même sélection.
- subset(fr, select = c(age)) : sélectione le sous dataframe en retenant les colonnes indiquées (sans quotes !)
- subset(fr, select = - c(age)) : sélectione le sous dataframe en enlevant les colonnes indiquées.
Sélection de lignes avec des expressions booléennes :
- fr[fr$nom == "jean" | ! fr$age > 35, ] : combinaison de critères (avec opérateurs booléens '|', '&' et '!')
- subset(fr, nom == "jean" | ! age > 35) : autre façon.
Elimination des doublons dans un dataframe : grâce à unique :
fr <- data.frame(A = factor(c("a", "b", "a")), B = c(3, 4, 3))
unique(fr)
A B
1 a 3
2 b 4
Calcul d'agrégats par groupe avec
by (souvent plus facile d'utiliser aggregate ci-dessous) :
- Si fr <- data.frame(typ = factor(c("a", "b", "b", "a", "b")), val = c(3, 5, 2, 3, 1)), alors res <- by(fr$val, fr$typ, sum) : calcule la somme des valeurs de val par valeur de typ.
- Le résultat est un objet de type by (une liste) : par exemple, res[["a"]] ou res[[1]] donne 6.
Calcul d'agrégats par groupe avec
aggregate (beaucoup plus commode) :
- aggregate(fr$val, by = list(typ2 = fr$typ), sum) : calcule aussi la somme des valeurs de val par valeur de typ, mais renvoie un objet de type dataframe.
typ2 x
1 a 6
2 b 8
- On peut donner une fonction quelconque, y compris anonyme : aggregate(fr$val, by = list(typ = fr$typ), function(vect) {sqrt(sum(vect ^ 2))}).
- Pour éviter que la colonne d'agrégat porte le nom de x et lui donner le nom que l'on souhaite : aggregate(data.frame(somme = fr$val), by = list(typ2 = fr$typ), sum).
- Le paramètre "by" peut prendre une liste de plusieurs colonnes pour faire un agrégat selon plusieurs colonnes.
fr <- data.frame(typ = factor(c("a", "b", "b", "a", "b")),
typ2 = factor(c("A", "B", "B", "B", "B")),
val = c(3, 5, 2, 3, 1))
aggregate(data.frame(val = fr$val), by = list(typ = fr$typ, typ2 = fr$typ2), mean)
donne :
typ typ2 val
1 a A 3.000000
2 a B 3.000000
3 b B 2.666667
Passage d'un dataframe avec 2 facteurs à une matrice, avec aggrégation des valeurs au passage (souvent avec moyenne) :
fr <- data.frame(typ = factor(c("a", "b", "b", "a", "b")),
typ2 = factor(c("A", "B", "B", "B", "B")),
val = c(3, 5, 2, 3, 1))
tapply(fr$val, list(typ = fr$typ, typ2 = fr$typ2), mean)
donne
typ2
typ A B
a 3 3.000000
b NA 2.666667
le résultat est une matrice.
Jointure de frames (au sens relationnel) :
Si
fr1 <-data.frame(val1 = c("a", "b"), val2 = c(2, 4)); fr2 <- data.frame(val2 = c(2, 3, 4), val3 = c("b", "c", "a")) :
- merge(fr1, fr2) : fait une jointure sur les colonnes qui ont même nom (il peut y en avoir plusieurs).
val2 val1 val3
1 2 a b
2 4 b a
- merge(fr1, fr2, by = c("val2")) : précise les noms des colonnes sur lesquelles on fait la jointure (si on ne veut en utiliser qu'une partie).
- merge(fr1, fr2, by.x = c("val1"), by.y = c("val3")) : indique dque l'on doit faire la jointure sur d'autre colonnes que celles de même nom dans chaque frame (val1 côté fr1 et val3 côté fr2).
val1 val2.x val2.y
1 a 2 4
2 b 4 2
- merge(fr1, fr2, by.x = 1, by.y = 2) : idem, mais en précisant le numéro des colonnes plutôt que leur nom.
- merge(fr1, fr2, all = TRUE) : fait une jointure externe des deux côtés (conserve les lignes qui n'ont pas de correspondance dans l'autre frame en rajoutant des NA dans les cases indéterminées :
val2 val1 val3
1 2 a b
2 3 <NA> c
3 4 b a
- merge(fr1, fr2, all.y = TRUE) : fait une jointure externe seulement du côté du 2ème dataframe (all.x = TRUE pour le premier dataframe).
Calcul d'aggrégats multiples (par exemple, on veut calculer sur chaque groupe à la fois la moyenne et l'écart-type des valeurs d'une colonne) : utiliser pour cela le package doBy (non installé par défaut) :
- Aggrégats en donnant le nom de fonction prédéfinies :
library(doBy)
fr <- data.frame(lab = c("A", "B", "A", "B", "B", "A", "B", "B", "B", "B"),
val = c(1, 5, 2, 6, 7, 3, 6, 8, 5, 7))
summaryBy(val ~ lab, fr, FUN = c(mean, sd, length))
donne :
lab val.mean val.sd val.length
1 A 2.000000 1.000000 3
2 B 6.285714 1.112697 7
- Aggrégats en donnant une fonction customisée qui renvoie plusieurs variables :
library(doBy)
fr <- data.frame(lab = c("A", "B", "A", "B", "B", "A", "B", "B", "B", "B"),
val = c(1, 5, 2, 6, 7, 3, 6, 8, 5, 7))
summaryBy(val ~ lab, fr, FUN = function(x) {return(c(mean(x), sd(x), length(x)))})
donne :
lab val.mean val.sd val.length
1 A 2.000000 1.000000 3
2 B 6.285714 1.112697 7
- Aggrégats en faisant des groupes selon les valeurs de plusieurs variables :
library(doBy)
fr <- data.frame(lab1 = c("A", "B", "A", "B", "B", "A", "B", "B", "B", "B"),
lab2 = c("a", "a", "b", "b", "a", "a", "a", "b", "b", "a"),
val = c(1, 5, 2, 6, 7, 3, 6, 8, 5, 7))
summaryBy(val ~ lab1 + lab2, fr, FUN = c(mean, sd))
donne :
lab1 lab2 val.mean val.sd
1 A a 2.000000 1.4142136
2 A b 2.000000 NA
3 B a 6.250000 0.9574271
4 B b 6.333333 1.5275252
Tri d'un frame selon une valeur :
library(doBy)
fr <- data.frame(lab = c("A", "B", "A", "B", "B", "A", "B", "B", "B", "B"),
val = c(1, 5, 2, 6, 7, 3, 6, 8, 5, 7))
orderBy(~ lab, fr)
donne :
lab val
1 A 1
3 A 2
6 A 3
2 B 5
4 B 6
5 B 7
7 B 6
8 B 8
9 B 5
10 B 7
Stacking/unstacking de frames :
Transformation d'une matrice en data-frame à colonnes avec les noms des lignes et des colonnes de la matrice et les valeurs :
mat <- matrix(c(1, 2, 3, 4, 5, 6), nrow = 3,
dimnames = list(c("A", "B", "C"), c("a", "b")))
print(mat)
fr <- data.frame(varLine = rep(rownames(mat), times = ncol(mat)),
varColumn = rep(colnames(mat), each = nrow(mat)),
values = as.vector(mat))
print(fr)
donne :
a b
A 1 4
B 2 5
C 3 6
varLine varColumn values
1 A a 1
2 B a 2
3 C a 3
4 A b 4
5 B b 5
6 C b 6
Split de valeurs selon un facteur :
Si fr est le dataframe :
typ val
1 a 3
2 b 5
3 b 2
4 a 3
5 b 1
split(fr$val, fr$typ) : partage les valeurs de fr$val selon les valeurs de fr$typ pour donner une liste dont les éléments sont les vecteurs de valeurs de fr$val par valeur de fr$typ :
$a
[1] 3 3
$b
[1] 5 2 1
Vérification du l'équilibre d'un design, avec la fonction
replications :
- si on part d'un design équilibré :
fr <- data.frame(val = c(1, 2, 4, 5, 6, 3, 3, 2),
g1 = c("a", "b", "a", "b", "a", "b", "a", "b"),
g2 = c("A", "A", "A", "A", "B", "B", "B", "B"))
- vérification de l'équilibre du design par rapport à l'un des groupes :
> replications(val ~ g1, fr)
g1
4
4 lignes pour chaque valeur
- vérification de l'équilibre du design par rapport aux 2 groupes indépendamment :
> replications(val ~ g1 + g2, fr)
g1 g2
4 4
4 lignes pour chaque valeur de chaque groupe
- si il y a un déséquilibre, la sortie est plus complexe : donne pour chaque groupe le nombre de lignes pour chaque valeur de ce groupe :
> replications(val ~ g1 + g2, fr[1:7,])
$g1
g1
a b
4 3
$g2
g2
A B
4 3
- vérification de l'équilibre du design avec les combinaisons de valeurs des différents groupes :
> replications(val ~ g1 * g2, fr)
g1 g2 g1:g2
4 4 2
il y a 2 lignes pour chaque combinaison de valeurs de g1 et g2
Copyright Aymeric Duclert
programmer en R, tutoriel R, graphes en R