Подтвердить что ты не робот

Разделить 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. Какой лучший способ сделать это?

Спасибо.

4b9b3361

Ответ 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)
)