R Language
Функция разделения
Поиск…
Основное использование раскола
split
позволяет разделить вектор или data.frame на ведра в отношении переменных фактора / группы. Эта вентиляция в ведрах принимает форму списка, который затем может использоваться для применения группового вычисления ( for
циклов или lapply
/ sapply
).
В первом примере показано использование split
на вектор:
Рассмотрим следующий вектор букв:
testdata <- c("e", "o", "r", "g", "a", "y", "w", "q", "i", "s", "b", "v", "x", "h", "u")
Цель состоит в том, чтобы отделить эти буквы от voyels
и consonants
, т. voyels
Разделить их на буквенный тип.
Сначала создадим вектор группировки:
vowels <- c('a','e','i','o','u','y')
letter_type <- ifelse(testdata %in% vowels, "vowels", "consonants")
Обратите внимание, что letter_type
имеет ту же длину, что и наши векторные testdata
. Теперь мы можем split
эти тестовые данные на две группы, vowels
и consonants
:
split(testdata, letter_type)
#$consonants
#[1] "r" "g" "w" "q" "s" "b" "v" "x" "h"
#$vowels
#[1] "e" "o" "a" "y" "i" "u"
Следовательно, результатом является список, имена которого исходят из нашего вектора letter_type
/ factor letter_type
.
split
также имеет метод работы с data.frames.
Рассмотрим, например, данные iris
:
data(iris)
Используя split
, можно создать список, содержащий один файл data.frame per 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
(содержит только данные для группы setosa).
Одной из примерных операций было бы вычисление матрицы корреляции для каждой диафрагмы; тогда можно было бы использовать 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
Затем мы можем получить для каждой группы лучшую пару коррелированных переменных: (корреляционная матрица изменена / расплавлена, диагональ отфильтрована и выполняется выбор наилучшей записи)
> 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
Обратите внимание, что одни вычисления выполняются на таком групповом уровне, может быть интересен укладку результатов, что можно сделать с помощью:
> (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 в парадигме split-apply-comb
Популярной формой анализа данных является split-apply-comb , в котором вы разбиваете свои данные на группы, применяете какую-то обработку в каждой группе, а затем объединяете результаты.
Рассмотрим анализ данных, где мы хотим получить два автомобиля с лучшими милями на галлон (миль на галлон) для каждого количества цилиндров (цил) во встроенном наборе данных mtcars. Во-первых, мы разделили mtcars
данных mtcars
на количество цилиндров:
(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
# ...
Это вернуло список кадров данных, по одному для каждого подсчета баллонов. Как видно из вывода, мы могли бы получить соответствующие фреймы данных с помощью spl$`4`
, spl$`6`
и spl$`8`
(некоторые могут показаться более визуально привлекательными для использования spl$"4"
или spl[["4"]]
).
Теперь мы можем использовать lapply
чтобы перебирать этот список, применяя нашу функцию, которая извлекает автомобили с лучшими значениями 2 mpg от каждого элемента списка:
(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
Наконец, мы можем объединить все вместе, используя rbind
. Мы хотим называть rbind(best2[["4"]], best2[["6"]], best2[["8"]])
, но это было бы утомительно, если бы у нас был огромный список. В результате мы используем:
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
Это возвращает результат rbind
(аргумент 1, функция) со всеми элементами best2
(аргумент 2, список), переданный в качестве аргументов.
С помощью простых анализов, подобных этому, он может быть более компактным (и, возможно, гораздо менее читаемым!), Чтобы сделать весь split-apply-comb в одной строке кода:
do.call(rbind, lapply(split(mtcars, mtcars$cyl), function(x) tail(x[order(x$mpg),], 2)))
Стоит также отметить, что lapply(split(x,f), FUN)
может быть альтернативно обрамлена с ?by
функции:
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)))