R Language
Split functie
Zoeken…
Basisgebruik van split
split
maakt het mogelijk om een vector of een data.frame in emmers te verdelen met betrekking tot een factor / groepsvariabelen. Deze ventilatie in emmers neemt de vorm aan van een lijst, die vervolgens kan worden gebruikt om groepsgewijze berekening toe te passen ( for
lussen of lapply
/ sapply
).
Eerste voorbeeld toont het gebruik van split
op een vector:
Overweeg de volgende vector letters:
testdata <- c("e", "o", "r", "g", "a", "y", "w", "q", "i", "s", "b", "v", "x", "h", "u")
Doel is om die letters te scheiden in voyels
en consonants
, dat wil zeggen deze op te splitsen naar lettertype.
Laten we eerst een groeperingsvector maken:
vowels <- c('a','e','i','o','u','y')
letter_type <- ifelse(testdata %in% vowels, "vowels", "consonants")
Merk op dat letter_type
dezelfde lengte heeft die onze vector testdata
. Nu kunnen we deze testgegevens split
in de twee groepen, vowels
en consonants
:
split(testdata, letter_type)
#$consonants
#[1] "r" "g" "w" "q" "s" "b" "v" "x" "h"
#$vowels
#[1] "e" "o" "a" "y" "i" "u"
Het resultaat is dus een lijst met namen die afkomstig zijn van onze groepering vector / factor letter_type
.
split
heeft ook een methode om met data.frames om te gaan.
Overweeg bijvoorbeeld iris
:
data(iris)
Door split
, kan men een lijst maken met één data.frame per irisspecie (variabele: 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
(bevat alleen gegevens voor setosa-groep).
Een voorbeeld van een bewerking zou zijn om de correlatiematrix per irissoort te berekenen; men zou dan 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
Dan kunnen we per groep het beste paar gecorreleerde variabelen ophalen: (correlatiematrix wordt hervormd / gesmolten, diagonaal wordt uitgefilterd en het selecteren van de beste record wordt uitgevoerd)
> 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
Merk op dat één berekeningen op een dergelijk groepsgewijs niveau worden uitgevoerd, dat men misschien geïnteresseerd is in het stapelen van de resultaten, wat kan worden gedaan met:
> (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
Split gebruiken in het split-apply-combineren paradigma
Een populaire vorm van gegevensanalyse is split-apply-combineren , waarin u uw gegevens in groepen splitst, een soort verwerking op elke groep toepast en vervolgens de resultaten combineert.
Laten we een gegevensanalyse overwegen waarbij we de twee auto's met de beste mijl per gallon (mpg) voor elke cilindertelling (cyl) in de ingebouwde mtcars-gegevensset willen verkrijgen. Eerst splitsen we het mtcars
gegevensframe op aantal cilinders:
(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
# ...
Dit heeft een lijst met gegevensframes geretourneerd, één voor elke cilindertelling. Zoals aangegeven door de uitvoer, kunnen we de relevante spl$`6`
verkrijgen met spl$`4`
, spl$`6`
en spl$`8`
(sommigen vinden het visueel aantrekkelijker om spl$"4"
of spl[["4"]]
plaats daarvan).
Nu kunnen we lapply
om door deze lijst te bladeren en onze functie toe te passen die de auto's met de beste 2 mpg-waarden uit elk van de lapply
extraheert:
(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
Eindelijk kunnen we alles combineren met behulp van rbind
. We willen rbind(best2[["4"]], best2[["6"]], best2[["8"]])
, maar dit zou vervelend zijn als we een enorme lijst hadden. Daarom gebruiken we:
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
Dit retourneert het resultaat van rbind
(argument 1, een functie) waarbij alle elementen van best2
(argument 2, een lijst) zijn doorgegeven als argumenten.
Met eenvoudige analyses zoals deze kan het compacter (en mogelijk veel minder leesbaar!) Zijn om de hele split-apply-maaidorser in een enkele coderegel te doen:
do.call(rbind, lapply(split(mtcars, mtcars$cyl), function(x) tail(x[order(x$mpg),], 2)))
Het is ook vermeldenswaard dat de lapply(split(x,f), FUN)
als alternatief kan worden ingelijst met de functie ?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)))