R基于多个列值将数据帧子集为多个数据帧

R基于多个列值将数据帧子集为多个数据帧,r,dataframe,subset,multiple-columns,R,Dataframe,Subset,Multiple Columns,我正在尝试对一个数据帧进行子集划分,其中我基于多个列值获得多个数据帧。这是我的例子 >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

我正在尝试对一个数据帧进行子集划分,其中我基于多个列值获得多个数据帧。这是我的例子

>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
我已经写了一个代码,现在正在运行,但不认为这是最好的方法。一定有更好的办法。假设
选项卡
是具有初始数据的data.frame。这是我的密码:

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)
  }
}

v1Factors您正在寻找的
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
看来
交互
稍微快一点(可能是因为
f=list(…)
刚刚转换为函数内的交互)


编辑

如果您只想使用子集data.frames,那么我建议使用data.table以便于编码

library(data.table)

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

dt现在还有来自
tidyr
nest()
,这相当不错

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
library(tidyr)
nestdf%nest(v3:v5)
NESDF$数据
>NESDF$数据
[[1]]
#一个tibble:2×3
v3 v4 v5
1     1    10    12
2     1    10    12
[[2]]
#一个tibble:1×3
v3 v4 v5
1    10    12     8
[[3]]
#一个tibble:2×3
v3 v4 v5
1     2    12    15
2     2    14    16

使用
nestdf$data[1]
等访问单个TIB文件。

您想重用这些数据帧,还是只打印按这些列分组的数据帧?我想重用它们。。。。想要在这些数据帧上绘制图形。
split
可以获取
f
的列表,而不必使用
交互
。不知道哪一个更有效。谢谢你的基准测试。在这种情况下,@Arun的把戏(
with(df,split(df,f=do.call)(paste,df[1:2]))
可能会更快!而且,这不会创建需要删除的不必要的级别。@mnel感谢您的及时回复。您的建议似乎确实有效。但并没有完全理解您所建议的多种方法的区别。@mnel看起来像是交互创建了所有可能的级别组合。但是当我运行了上面提到的示例,它没有创建所有级别。为什么呢?在实际数据集中,它正在创建…这让我感到困惑。