在R中对数据框中的分组应用函数

14

我试图获取数据框内变量v的分组累计和,分组为“a”和“b”。如何将最终结果存储到数据框的列cs中,行数为偶数?

> library(nlme)
> g <- factor(c("a","b","a","b","a","b","a","b","a","b","a","b"))
> v <- c(1,4,1,4,1,4,2,8,2,8,2,8)
> cs <- rep(0,12)
> d <- data.frame(g,v,cs)

> d
   g v cs
1  a 1 0
2  b 4 0
3  a 1 0
4  b 4 0
5  a 1 0
6  b 4 0
7  a 2 0
8  b 8 0
9  a 2 0
10 b 8 0
11 a 2 0
12 b 8 0

> r=gapply(d,FUN="cumsum",form=~g, which="v")
>r

$a     
   v   
1  1   
3  2   
5  3  
7  5  
9  7  
11 9  

$b    
    v 
2   4 
4   8 
6  12 
8  20 
10 28 
12 36 

> str(r)
List of 2
 $ a:'data.frame':  6 obs. of  1 variable:
  ..$ v: num [1:6] 1 2 3 5 7 9
 $ b:'data.frame':  6 obs. of  1 variable:
  ..$ v: num [1:6] 4 8 12 20 28 36

我想我可以想出一些费力的方法将这些数据框中的数据传递到d$cs中,但我肯定有所遗漏,应该有一些简单的小技巧。

4个回答

13

split<- 是一种相当奇怪的语法结构

split(d$cs, d$g) <- lapply(split(d$v, d$g), cumsum)

导致

> d
   g v cs
1  a 1  1
2  b 4  4
3  a 1  2
4  b 4  8
5  a 1  3
6  b 4 12
7  a 2  5
8  b 8 20
9  a 2  7
10 b 8 28
11 a 2  9
12 b 8 36

3
那是split<-.default。我没有意识到它的存在(或者它是ave的基础)。split<-.data.frame甚至更奇怪。 - IRTFM

10

我会使用ave。如果您查看ave的源代码,您会发现它本质上是将Martin Morgan的解决方案进行了包装。

R> g <- factor(c("a","b","a","b","a","b","a","b","a","b","a","b"))
R> v <- c(1,4,1,4,1,4,2,8,2,8,2,8)
R> d <- data.frame(g,v)
R> d$cs <- ave(v, g, FUN=cumsum)
R> d
   g v cs
1  a 1  1
2  b 4  4
3  a 1  2
4  b 4  8
5  a 1  3
6  b 4 12
7  a 2  5
8  b 8 20
9  a 2  7
10 b 8 28
11 a 2  9
12 b 8 36

我总是忘记 ave;虽然它的结果与另外两个相同吗? - Tyler Rinker
@TylerRinker:它基本上与Martin的解决方案相同(请参见我的编辑)。 - Joshua Ulrich
我感到困惑,因为我与Joran的进行了比较。我忘记了plyr会重新排列事物。+1 - Tyler Rinker
不错,将 ave 添加到我有用函数的心理库中。 - thelatemail
谢谢!这是最简单的,所以我选择它。 - exzackley
我可以使用自己的函数来计算累积和吗?(用我的函数替换cumsum)。在这种情况下,我的函数需要什么输入? - Prince Bhatti

7

对于这些事情,我选择的工具是plyr软件包:

require(plyr)
> ddply(d,.(g),transform,cs = cumsum(v))
   g v cs
1  a 1  1
2  a 1  2
3  a 1  3
4  a 2  5
5  a 2  7
6  a 2  9
7  b 4  4
8  b 4  8
9  b 4 12
10 b 8 20
11 b 8 28
12 b 8 36

0
> library(nlme)
> g <- factor(c("a","b","a","b","a","b","a","b","a","b","a","b"))
> v <- c(1,4,1,4,1,4,2,8,2,8,2,8)
> cs <- rep(0,12)
> d <- data.frame(g,v,cs)
> d <- d[order(d$g),]
> temp <- by(d$v,d$g,cumsum)
> d$cs <- do.call("c",temp)
> d
   g v cs
1  a 1  1
3  a 1  2
5  a 1  3
7  a 2  5
9  a 2  7
11 a 2  9
2  b 4  4
4  b 4  8
6  b 4 12
8  b 8 20
10 b 8 28
12 b 8 36

另一种使用 by 函数的解决方案,但我必须先对数据进行排序。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接