2017-10-28 111 views
3

我是R新手,我試圖使用dplyr根據行值摺疊行。以下示例顯示示例數據。使用dplyr摺疊行

set.seed(123)

df<-data.frame(A=c(rep(1:4,4)), B=runif(16,min=0,max=1), C=rnorm(16, mean=1,sd=0.5))

A B   c 
1 1 0.36647435 0.7485365 
2 2 0.51864614 0.8654337 
3 3 0.04596929 0.9858012 
4 4 0.15479619 1.1294208 
5 1 0.76712372 1.2460700 
6 2 0.17666676 0.7402996 
7 3 0.89759874 1.2699954 
8 4 0.90267735 0.7101804 
9 1 0.91744223 0.3451281 
10 2 0.25472599 0.8604743 
11 3 0.10933985 0.8696796 
12 4 0.71656017 1.2648846 
13 1 0.21157810 1.3170205 
14 2 0.14947268 1.2789700 
15 3 0.92251060 1.5696901 
16 4 0.30090579 1.7642853 

我想基於所述條件總結/合攏的兩行,在A列中的行具有值1和2爲一個行(如行1的平均值和2)。因此最終結果將只有12行,因爲其他4行已摺疊。

我試圖使用以下dplyr函數,但沒有多大用處。

install.packages( 「tidyverse」) 庫(tidyverse)

df %>% summarize_each(fun(i){ for i %in% c(1,2)funs(mean) }) 

預期的輸出是一樣的東西:

A B   C 
1 1.5 0.4425602 0.8069851 
3 3 0.04596929 0.9858012 
4 4 0.15479619 1.1294208 
5 1.5 0.4718952 0.9931848 
7 3 0.89759874 1.2699954 
8 4 0.90267735 0.7101804 
9 1.5 0.5860841 0.6028012 
11 3 0.10933985 0.8696796 
12 4 0.71656017 1.2648846 
13 1.5 0.1805254 1.297995 
15 3 0.92251060 1.5696901 
16 4 0.30090579 1.7642853 

預先感謝您。

+0

行沒有完全摺疊,它們是2×2倒塌,你不解釋規則,在你的真實數據中,你真的有4行的序列,像這樣? –

+0

@Moody_Mudskipper如果列A中的值爲1和2,則行將被摺疊。 – G1124E

+0

生成隨機數據時,在您的示例中包含'set.seed()'調用將會很有幫助。這樣其他人可以準確地複製你的結果! –

回答

1

通過使隱式的,基於訂單的分組明確,總結可以用單個summarise_all調用完成。

# Generate the data 
set.seed(1) 

df <- data.frame(
    A = c(rep(1:4, 4)), 
    B = runif(16, min = 0, max = 1), 
    C = rnorm(16, mean = 1, sd = 0.5) 
) 

library(dplyr) 

new <- df %>% 
    group_by(grp = rep(
    1:4,  # vector containing names of groups to create 
    each = 4 # number of elements in each group 
)) %>% 
    group_by(mean_grp = cumsum(A > 2) + 1, add = T) %>% 
    summarise_all(mean) %>% 
    ungroup() 

new 
#> # A tibble: 12 x 5 
#>  grp mean_grp  A   B   C 
#> <int> <dbl> <dbl>  <dbl>  <dbl> 
#> 1  1  1 1.5 0.3188163 1.067598241 
#> 2  1  2 3.0 0.5728534 1.755890584 
#> 3  1  3 4.0 0.9082078 1.194921618 
#> 4  2  1 1.5 0.5500358 0.291014883 
#> 5  2  2 3.0 0.9446753 1.562465459 
#> 6  2  3 4.0 0.6607978 0.977533195 
#> 7  3  1 1.5 0.3454502 1.231911487 
#> 8  3  2 3.0 0.2059746 1.410610598 
#> 9  3  3 4.0 0.1765568 1.296950661 
#> 10  4  1 1.5 0.5355633 1.425278418 
#> 11  4  2 3.0 0.7698414 1.037282492 
#> 12  4  3 4.0 0.4976992 0.005324152 

我會建議保持分組變量在您的數據 彙總後(一切都是簡單的,如果你將它們包含在第1名), 但如果你願意,你可以用 new %>% select(-grp, -mean_grp)刪除它們。


PS。爲了避免具有"magic numbers"(創建grp當如1:4each = 4)包括在所述代碼中,也可以創建所述第一分組變量爲:

grp = cumsum(A < lag(A, default = A[1])) + 1 

假設原來的數據被排序,使得一個新的組每次啓動時,A的值都小於之前的值A

+1

我試着運行代碼,但是我得到了這個錯誤信息:'mutate_impl(.data,dots)錯誤: 錯誤結果size(64),expected 16 or 1'我不確定爲什麼我們需要第一個'group_by'函數中的'each = 4'參數。我也嘗試通過省略'each = 4'參數來運行代碼,但輸出沒有排序。如預期。你可以請說一說嗎? – G1124E

+0

啊,這是一個錯字:一定是在做一些造型時留下的。你可以省略第一個'4',但你需要'each'將4個相鄰的行組合在一起。我已經編輯過。 –

1

一種選擇是與A等於1或2的從其它行處理的行分開,然後將它們綁定到一起:

set.seed(3) 
df<-data.frame(A=c(rep(1:4,4)),B=runif(16,min=0,max=1),c=rnorm(16, mean=1,sd=0.5)) 

df %>% 
    filter(A %in% 1:2) %>% 
    group_by(tmp=cumsum(A==1)) %>% 
    summarise_all(mean) %>% 
    ungroup %>% select(-tmp) %>% 
    bind_rows(df %>% filter(!A %in% 1:2)) 
 A   B   c 
    <dbl>  <dbl>  <dbl> 
1 1.5 0.4877790 1.0121278 
2 1.5 0.6032474 0.8840735 
3 1.5 0.6042946 0.5996850 
4 1.5 0.5456424 0.6198039 
5 3.0 0.3849424 0.6276092 
6 4.0 0.3277343 0.4343907 
7 3.0 0.1246334 1.0760229 
8 4.0 0.2946009 0.8461718 
9 3.0 0.5120159 1.6121568 
10 4.0 0.5050239 1.0999058 
11 3.0 0.8679195 0.8981359 
12 4.0 0.8297087 0.1667626 
+0

謝謝@ eipi10我想知道如何保留行的順序,所以行可以按照增加的順序排列; 1.5,3,4,1.5 3,4,1.5 3,4,1.5 3,4. – G1124E