2013-03-13 170 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]等。

相關問題