将data.frame基于因子的级别拆分为新的data.frames

时间:2012-03-15 02:43:06

标签: r r-faq

我正在尝试根据因素的级别创建单独的data.frame个对象。如果我有:

df <- data.frame(
  x=rnorm(25),
  y=rnorm(25),
  g=rep(factor(LETTERS[1:5]), 5)
)

如何将df拆分为包含相应data.frameg值的x每个级别的单独y?我可以使用split(df, df$g)获取大部分内容,但我希望每个级别的因子都有自己的data.frame。最好的方法是什么?

感谢。

2 个答案:

答案 0 :(得分:77)

我认为split完全符合您的要求。

请注意,X是一个数据框列表,如str所示:

X <- split(df, df$g)
str(X)

如果您希望具有组g名称的单个对象,您可以将split中的X元素分配给这些名称的对象,但是当您只能从列表中索引数据帧时,这似乎是额外的工作{ {1}}创建。

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

答案 1 :(得分:3)

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::splitdplyr::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"

数据

set.seed(1234)
df <- data.frame(
      x=rnorm(25),
      y=rnorm(25),
      g=rep(factor(LETTERS[1:5]), 5)
)