2017-10-28 112 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