2013-03-13 171 views
19

我想要一个数据框子集,其中我得到基于多个列值的多个数据帧。这是我的例子R基于多个列值将数据帧分成多个数据帧

>df 
    v1 v2 v3 v4 v5 
    A Z 1 10 12 
    D Y 10 12 8 
    E X 2 12 15 
    A Z 1 10 12 
    E X 2 14 16 

预期输出是这样的我在哪里分裂这个数据帧为基于v1列中的多个数据帧和v2

>df1 
v3 v4 v5 
    1 10 12 
    1 10 12 
>df2 
v3 v4 v5 
10 12 8 
>df3 
v3 v4 v5 
2 12 15 
2 14 16 

我已经写了这是工作守则现在,但不认为这是做到这一点的最佳方式。必须有更好的方法来做到这一点。假设tab是具有初始数据的数据帧。这是我的代码:

v1Factors<-levels(factor(tab$v1)) 
v2Factors<-levels(factor(tab$v2)) 

for(i in 1:length(v1Factors)){ 
    for(j in 1:length(v2Factors)){ 
    subsetTab<-subset(tab, v1==v1Factors[i] & v2==v2Factors[j], select=c("v3", "v4", "v5")) 
    print(subsetTab) 
    } 
} 

有人可以建议一个更好的方法来做到上述?

+0

你想重用这些数据框,还是只打印它们按这些列分组? – Thilo 2013-03-13 04:45:52

+0

我想重复使用它们....想要在这些数据框上绘制图表。 – 2013-03-13 04:46:37

回答

23

您正在寻找split

split(df, with(df, interaction(v1,v2)), drop = TRUE) 
$E.X 
    v1 v2 v3 v4 v5 
3 E X 2 12 15 
5 E X 2 14 16 

$D.Y 
    v1 v2 v3 v4 v5 
2 D Y 10 12 8 

$A.Z 
    v1 v2 v3 v4 v5 
1 A Z 1 10 12 

正如评论指出

以下任一会工作

library(microbenchmark) 
microbenchmark(
       split(df, list(df$v1,df$v2), drop = TRUE), 
       split(df, interaction(df$v1,df$v2), drop = TRUE), 
       split(df, with(df, interaction(v1,v2)), drop = TRUE)) 


Unit: microseconds 
                expr  min  lq median  uq  max neval 
      split(df, list(df$v1, df$v2), drop = TRUE) 1119.845 1129.3750 1145.8815 1182.119 3910.249 100 
    split(df, interaction(df$v1, df$v2), drop = TRUE) 893.749 900.5720 909.8035 936.414 3617.038 100 
split(df, with(df, interaction(v1, v2)), drop = TRUE) 895.150 902.5705 909.8505 927.128 1399.284 100 

看来interaction稍微快一些(可能是由于以下事实: f = list(...)只是转换为功能内的交互)


编辑

如果你只是想使用子data.frames然后

library(data.table) 

dt <- data.table(df) 
dt[, plot(v4, v5), by = list(v1, v2)] 
+2

'split'可以采用'f'列表,而不必使用'interaction'。不知道哪个更有效。 – A5C1D2H2I1M1N2O1R2T1 2013-03-13 04:48:25

+0

@AnandaMahto - 我添加了一个基准。 – mnel 2013-03-13 04:53:52

+0

感谢您的基准。在这种情况下,@ Arun的诀窍('with(df,split(df,f = do.call(paste,df [1:2])))'可能会更快!而且,这不会产生不必要的级别 – A5C1D2H2I1M1N2O1R2T1 2013-03-13 04:58:52

3

现在有我会建议使用data.table易于编程也nest()tidyr这是相当不错的。

library(tidyr) 
nestdf <- df %>% nest(v3:v5) 
nestdf$data 

> nestdf$data 
[[1]] 
# A tibble: 2 × 3 
    v3 v4 v5 
    <int> <int> <int> 
1  1 10 12 
2  1 10 12 

[[2]] 
# A tibble: 1 × 3 
    v3 v4 v5 
    <int> <int> <int> 
1 10 12  8 

[[3]] 
# A tibble: 2 × 3 
    v3 v4 v5 
    <int> <int> <int> 
1  2 12 15 
2  2 14 16 

访问个人tibbles与nestdf$data[1]等。

相关问题