使用dplyr group_by模拟split():返回数据框列表

时间:2015-11-18 08:40:05

标签: r list split dplyr

我有一个大的数据集在R中扼杀了split()。我可以使用dplyr group_by(无论如何这是一种首选方式)但是我无法保留生成的grouped_df作为数据框列表,我的连续处理步骤所需的格式(我需要强制转换为SpatialDataFrames和类似)。

考虑样本数据集:

df = as.data.frame(cbind(c("a","a","b","b","c"),c(1,2,3,4,5), c(2,3,4,2,2)))
listDf = split(df,df$V1)

返回

$a
   V1 V2 V3
 1  a  1  2
 2  a  2  3

$b
   V1 V2 V3
 3  b  3  4
 4  b  4  2

$c
   V1 V2 V3
 5  c  5  2

我想用group_by(类似group_by(df,V1))来模仿这个,但这会返回一个grouped_df。我知道do应该可以帮助我,但我不确定使用情况(另请参阅link进行讨论。)

请注意,将每个列表的名称拆分为用于建立此组的因子的名称 - 这是一个所需的函数(最终,这是从dfs列表中提取这些名称的方法的奖励)。

6 个答案:

答案 0 :(得分:15)

比较基础,pngplyr解决方案,它似乎仍然快得多!

dplyr

给出:

library(plyr)
library(dplyr)   

df <- data_frame(Group1=rep(LETTERS, each=1000),
             Group2=rep(rep(1:10, each=100),26), 
             Value=rnorm(26*1000))

microbenchmark(Base=df %>%
             split(list(.$Group2, .$Group1)),
           dplyr=df %>% 
             group_by(Group1, Group2) %>% 
             do(data = (.)) %>% 
             select(data) %>% 
             lapply(function(x) {(x)}) %>% .[[1]],
           plyr=dlply(df, c("Group1", "Group2"), as.tbl),
           times=50) 

答案 1 :(得分:13)

坚持&#39;对于dplyr,您也可以使用plyr代替split

library(plyr)

dlply(df, "V1", identity)
#$a
#  V1 V2 V3
#1  a  1  2
#2  a  2  3

#$b
#  V1 V2 V3
#1  b  3  4
#2  b  4  2

#$c
#  V1 V2 V3
#1  c  5  2

答案 2 :(得分:9)

只要您为存储数据框的新列命名,然后将该列导入group_by,您就可以使用dolapply获取数据框列表。

listDf = df %>% group_by(V1) %>% do(vals=data.frame(.)) %>% select(vals) %>% lapply(function(x) {(x)})
listDf[[1]]
#[[1]]
#  V1 V2 V3
#1  a  1  2
#2  a  2  3

#[[2]]
#  V1 V2 V3
#1  b  3  4
#2  b  4  2

#[[3]]
#  V1 V2 V3
#1  c  5  2

答案 3 :(得分:6)

group_split in dplyr 0.8:

dplyr的0.8版已实现group_splithttps://dplyr.tidyverse.org/reference/group_split.html

它将数据框按组划分,返回数据框列表。这些数据帧中的每一个都是由分割变量的类别定义的原始数据帧的子集。

例如。用变量iris分割数据集Species,并计算每个子数据集的摘要:

> iris %>% 
+     group_split(Species) %>% 
+     map(summary)
[[1]]
  Sepal.Length    Sepal.Width     Petal.Length    Petal.Width          Species  
 Min.   :4.300   Min.   :2.300   Min.   :1.000   Min.   :0.100   setosa    :50  
 1st Qu.:4.800   1st Qu.:3.200   1st Qu.:1.400   1st Qu.:0.200   versicolor: 0  
 Median :5.000   Median :3.400   Median :1.500   Median :0.200   virginica : 0  
 Mean   :5.006   Mean   :3.428   Mean   :1.462   Mean   :0.246                  
 3rd Qu.:5.200   3rd Qu.:3.675   3rd Qu.:1.575   3rd Qu.:0.300                  
 Max.   :5.800   Max.   :4.400   Max.   :1.900   Max.   :0.600                  

[[2]]
  Sepal.Length    Sepal.Width     Petal.Length   Petal.Width          Species  
 Min.   :4.900   Min.   :2.000   Min.   :3.00   Min.   :1.000   setosa    : 0  
 1st Qu.:5.600   1st Qu.:2.525   1st Qu.:4.00   1st Qu.:1.200   versicolor:50  
 Median :5.900   Median :2.800   Median :4.35   Median :1.300   virginica : 0  
 Mean   :5.936   Mean   :2.770   Mean   :4.26   Mean   :1.326                  
 3rd Qu.:6.300   3rd Qu.:3.000   3rd Qu.:4.60   3rd Qu.:1.500                  
 Max.   :7.000   Max.   :3.400   Max.   :5.10   Max.   :1.800                  

[[3]]
  Sepal.Length    Sepal.Width     Petal.Length    Petal.Width          Species  
 Min.   :4.900   Min.   :2.200   Min.   :4.500   Min.   :1.400   setosa    : 0  
 1st Qu.:6.225   1st Qu.:2.800   1st Qu.:5.100   1st Qu.:1.800   versicolor: 0  
 Median :6.500   Median :3.000   Median :5.550   Median :2.000   virginica :50  
 Mean   :6.588   Mean   :2.974   Mean   :5.552   Mean   :2.026                  
 3rd Qu.:6.900   3rd Qu.:3.175   3rd Qu.:5.875   3rd Qu.:2.300                  
 Max.   :7.900   Max.   :3.800   Max.   :6.900   Max.   :2.500     

它对于调试嵌套数据帧上的计算也非常有帮助,因为它是一种“查看”嵌套数据帧上“内部”计算的快速方法。

答案 4 :(得分:4)

dplyr 0.8 起,您可以使用group_split

library(dplyr)
df = as.data.frame(cbind(c("a","a","b","b","c"),c(1,2,3,4,5), c(2,3,4,2,2)))
df %>% group_by(V1) %>% group_split()
#> [[1]]
#> # A tibble: 2 x 3
#>   V1    V2    V3   
#>   <fct> <fct> <fct>
#> 1 a     1     2    
#> 2 a     2     3    
#> 
#> [[2]]
#> # A tibble: 2 x 3
#>   V1    V2    V3   
#>   <fct> <fct> <fct>
#> 1 b     3     4    
#> 2 b     4     2    
#> 
#> [[3]]
#> # A tibble: 1 x 3
#>   V1    V2    V3   
#>   <fct> <fct> <fct>
#> 1 c     5     2

答案 5 :(得分:3)

dplyr 0.5.0.9000起,使用group_by()的最短解决方案可能是在do之后加上pull

df %>% group_by(V1) %>% do(data=(.)) %>% pull(data)

请注意,与split不同,这没有命名结果列表元素。如果需要,那么您可能想要类似

df %>% group_by(V1) %>% do(data = (.)) %>% with( set_names(data, V1) )

稍微编辑一下,我同意人们所说的split()是更好的选择。就我个人而言,我总是感到很烦,我必须两次键入数据框的名称(例如,split( potentiallylongname, potentiallylongname$V1 )),但是这个问题很容易被管道避开:

df %>% split( .$V1 )