我有一个大的数据集在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列表中提取这些名称的方法的奖励)。
答案 0 :(得分:15)
比较基础,png
和plyr
解决方案,它似乎仍然快得多!
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
,您就可以使用do
从lapply
获取数据框列表。
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_split
:
https://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 )