Разделить data.frame на основе уровней фактора в новые data.frames
Я пытаюсь создать отдельные объекты data.frame
на основе уровней фактора. Поэтому, если у меня есть:
df <- data.frame(
x=rnorm(25),
y=rnorm(25),
g=rep(factor(LETTERS[1:5]), 5)
)
как я могу разделить df
на отдельный data.frame
для каждого уровня g
, содержащий соответствующие значения x
и y
? Я могу получить большую часть пути, используя split(df, df$g)
, но я бы хотел, чтобы каждый уровень фактора имел свой собственный data.frame
. Какой лучший способ сделать это?
Спасибо.
Ответы
Ответ 1
Я думаю, что split
делает именно то, что вы хотите.
Обратите внимание, что X - это список фреймов данных, как видно из str
:
X <- split(df, df$g)
str(X)
Если вам нужен отдельный объект с именами группы g, вы можете назначить элементы X из split
объектам этих имен, хотя это кажется дополнительной работой, когда вы можете просто индексировать кадры данных из списка split
создает.
#I used lapply just to drop the third column g which is no longer needed.
Y <- lapply(seq_along(X), function(x) as.data.frame(X[[x]])[, 1:2])
#Assign the dataframes in the list Y to individual objects
A <- Y[[1]]
B <- Y[[2]]
C <- Y[[3]]
D <- Y[[4]]
E <- Y[[5]]
#Or use lapply with assign to assign each piece to an object all at once
lapply(seq_along(Y), function(x) {
assign(c("A", "B", "C", "D", "E")[x], Y[[x]], envir=.GlobalEnv)
}
)
Изменить Или даже лучше, чем использовать lapply
для назначения глобальной среде использования list2env
:
names(Y) <- c("A", "B", "C", "D", "E")
list2env(Y, envir = .GlobalEnv)
A
Ответ 2
Начиная с dplyr 0.8.0
, мы также можем использовать group_split
, поведение которого аналогично base::split
library(dplyr)
df %>% group_split(g)
#[[1]]
# A tibble: 5 x 3
# x y g
# <dbl> <dbl> <fct>
#1 -1.21 -1.45 A
#2 0.506 1.10 A
#3 -0.477 -1.17 A
#4 -0.110 1.45 A
#5 0.134 -0.969 A
#[[2]]
# A tibble: 5 x 3
# x y g
# <dbl> <dbl> <fct>
#1 0.277 0.575 B
#2 -0.575 -0.476 B
#3 -0.998 -2.18 B
#4 -0.511 -1.07 B
#5 -0.491 -1.11 B
#....
Он также поставляется с аргументом keep
(по умолчанию TRUE
), чтобы указать, следует ли сохранять сгруппированный столбец или нет.
df %>% group_split(g, keep = FALSE)
#[[1]]
# A tibble: 5 x 2
# x y
# <dbl> <dbl>
#1 -1.21 -1.45
#2 0.506 1.10
#3 -0.477 -1.17
#4 -0.110 1.45
#5 0.134 -0.969
#[[2]]
# A tibble: 5 x 2
# x y
# <dbl> <dbl>
#1 0.277 0.575
#2 -0.575 -0.476
#3 -0.998 -2.18
#4 -0.511 -1.07
#5 -0.491 -1.11
#....
Разница между base::split
и dplyr::group_split
заключается в том, что group_split
не называет элементы списка на основе группировки. Так
df1 <- df %>% group_split(g)
names(df1) #gives
NULL
тогда
df2 <- split(df, df$g)
names(df2) #gives
#[1] "A" "B" "C" "D" "E"
data
данные
set.seed(1234)
df <- data.frame(
x=rnorm(25),
y=rnorm(25),
g=rep(factor(LETTERS[1:5]), 5)
)