Recherche…


Utilisation basique du split

split permet de diviser un vecteur ou un data.frame en compartiments par rapport à un facteur / groupe de variables. Cette ventilation en godets se présente sous la forme d'une liste, qui peut ensuite être utilisée pour appliquer un calcul par groupe ( for boucles ou par lapply / sapply ).

Le premier exemple montre l'utilisation de la split sur un vecteur:

Considérons le vecteur de lettres suivant:

testdata <- c("e", "o", "r", "g", "a", "y", "w", "q", "i", "s", "b", "v", "x", "h", "u")

L'objectif est de séparer ces lettres en voyels et en consonants , c'est-à-dire de les diviser en fonction du type de lettre.

Créons d'abord un vecteur de regroupement:

 vowels <- c('a','e','i','o','u','y')
 letter_type <- ifelse(testdata %in% vowels, "vowels", "consonants") 

Notez que letter_type a la même longueur que notre vecteur testdata . Maintenant, nous pouvons split ces données de test dans les deux groupes, vowels et consonants :

split(testdata, letter_type)
#$consonants
#[1] "r" "g" "w" "q" "s" "b" "v" "x" "h"

#$vowels
#[1] "e" "o" "a" "y" "i" "u"

Par conséquent, le résultat est une liste de noms provenant de notre vecteur de regroupement / facteur letter_type .

split a également une méthode pour gérer data.frames.

Considérons par exemple les données de l' iris :

data(iris)

En utilisant split , on peut créer une liste contenant un data.frame par espèce iris (variable: Species):

> liris <- split(iris, iris$Species)
> names(liris)
[1] "setosa"     "versicolor" "virginica"
> head(liris$setosa)
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
6          5.4         3.9          1.7         0.4  setosa

(contient uniquement des données pour le groupe setosa).

Un exemple d'opération serait de calculer une matrice de corrélation par espèce d'iris; on utiliserait alors lapply :

> (lcor <- lapply(liris, FUN=function(df) cor(df[,1:4])))

    $setosa
             Sepal.Length Sepal.Width Petal.Length Petal.Width
Sepal.Length    1.0000000   0.7425467    0.2671758   0.2780984
Sepal.Width     0.7425467   1.0000000    0.1777000   0.2327520
Petal.Length    0.2671758   0.1777000    1.0000000   0.3316300
Petal.Width     0.2780984   0.2327520    0.3316300   1.0000000

$versicolor
             Sepal.Length Sepal.Width Petal.Length Petal.Width
Sepal.Length    1.0000000   0.5259107    0.7540490   0.5464611
Sepal.Width     0.5259107   1.0000000    0.5605221   0.6639987
Petal.Length    0.7540490   0.5605221    1.0000000   0.7866681
Petal.Width     0.5464611   0.6639987    0.7866681   1.0000000

$virginica
             Sepal.Length Sepal.Width Petal.Length Petal.Width
Sepal.Length    1.0000000   0.4572278    0.8642247   0.2811077
Sepal.Width     0.4572278   1.0000000    0.4010446   0.5377280
Petal.Length    0.8642247   0.4010446    1.0000000   0.3221082
Petal.Width     0.2811077   0.5377280    0.3221082   1.0000000

Ensuite, nous pouvons récupérer par groupe la meilleure paire de variables corrélées: (la matrice de corrélation est remodelée / fondue, la diagonale est filtrée et la sélection du meilleur enregistrement est effectuée)

> library(reshape)
> (topcor <- lapply(lcor, FUN=function(cormat){
   correlations <- melt(cormat,variable_name="correlatio); 
   filtered <- correlations[correlations$X1 != correlations$X2,];
   filtered[which.max(filtered$correlation),]
}))    

$setosa
           X1           X2     correlation
2 Sepal.Width Sepal.Length       0.7425467

$versicolor
            X1           X2     correlation
12 Petal.Width Petal.Length       0.7866681

$virginica
            X1           X2     correlation
3 Petal.Length Sepal.Length       0.8642247

Notez que les calculs sont effectués à un tel niveau, on peut être intéressé par l’empilement des résultats, ce qui peut être fait avec:

> (result <- do.call("rbind", topcor))

                     X1           X2     correlation
setosa      Sepal.Width Sepal.Length       0.7425467
versicolor  Petal.Width Petal.Length       0.7866681
virginica  Petal.Length Sepal.Length       0.8642247

Utilisation de la division dans le paradigme split-apply-combine

Une forme populaire d'analyse de données est la méthode split-apply-combine , dans laquelle vous divisez vos données en groupes, appliquez une sorte de traitement à chaque groupe, puis combinez les résultats.

Considérons une analyse de données où nous voulons obtenir les deux voitures avec les meilleurs miles par gallon (mpg) pour chaque nombre de cylindres (cyl) dans le jeu de données intégré mtcars. Tout d'abord, nous mtcars le mtcars données mtcars par le nombre de cylindres:

(spl <- split(mtcars, mtcars$cyl))
# $`4`
#                 mpg cyl  disp  hp drat    wt  qsec vs am gear carb
# Datsun 710     22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
# Merc 240D      24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
# Merc 230       22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2
# Fiat 128       32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
# ...
# 
# $`6`
#                 mpg cyl  disp  hp drat    wt  qsec vs am gear carb
# Mazda RX4      21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
# Mazda RX4 Wag  21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
# Hornet 4 Drive 21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
# Valiant        18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
# ...
# 
# $`8`
#                      mpg cyl  disp  hp drat    wt  qsec vs am gear carb
# Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
# Duster 360          14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
# Merc 450SE          16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3
# Merc 450SL          17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3
# ...

Cela a renvoyé une liste de blocs de données, un pour chaque nombre de cylindres. Comme indiqué par la sortie, nous pourrions obtenir les trames de données pertinentes avec spl$`4` , spl$`6` et spl$`8` (certains pourraient trouver plus attrayant d'utiliser spl$"4" ou spl[["4"]] place).

Maintenant, nous pouvons utiliser lapply pour parcourir cette liste, en appliquant notre fonction qui extrait les voitures avec les 2 meilleures valeurs de mpg de chacun des éléments de la liste:

(best2 <- lapply(spl, function(x) tail(x[order(x$mpg),], 2)))
# $`4`
#                 mpg cyl disp hp drat    wt  qsec vs am gear carb
# Fiat 128       32.4   4 78.7 66 4.08 2.200 19.47  1  1    4    1
# Toyota Corolla 33.9   4 71.1 65 4.22 1.835 19.90  1  1    4    1
# 
# $`6`
#                 mpg cyl disp  hp drat    wt  qsec vs am gear carb
# Mazda RX4 Wag  21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
# Hornet 4 Drive 21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
# 
# $`8`
#                    mpg cyl disp  hp drat    wt  qsec vs am gear carb
# Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
# Pontiac Firebird  19.2   8  400 175 3.08 3.845 17.05  0  0    3    2

Enfin, nous pouvons tout combiner en utilisant rbind . Nous voulons appeler rbind(best2[["4"]], best2[["6"]], best2[["8"]]) , mais cela serait fastidieux si nous avions une liste énorme. En conséquence, nous utilisons:

do.call(rbind, best2)
#                      mpg cyl  disp  hp drat    wt  qsec vs am gear carb
# 4.Fiat 128          32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
# 4.Toyota Corolla    33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
# 6.Mazda RX4 Wag     21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
# 6.Hornet 4 Drive    21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
# 8.Hornet Sportabout 18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
# 8.Pontiac Firebird  19.2   8 400.0 175 3.08 3.845 17.05  0  0    3    2

Cela retourne le résultat de rbind (argument 1, une fonction) avec tous les éléments de best2 (argument 2, une liste) passés en arguments.

Avec des analyses simples comme celle-ci, il peut être plus compact (et peut-être beaucoup moins lisible!) De faire tout le split-apply-combine en une seule ligne de code:

do.call(rbind, lapply(split(mtcars, mtcars$cyl), function(x) tail(x[order(x$mpg),], 2)))

Il est également intéressant de noter que la lapply(split(x,f), FUN) peut être alternativement cadrée en utilisant la fonction ?by lapply(split(x,f), FUN) :

by(mtcars, mtcars$cyl, function(x) tail(x[order(x$mpg),], 2))
do.call(rbind, by(mtcars, mtcars$cyl, function(x) tail(x[order(x$mpg),], 2)))


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow