2012-05-18 34 views
13

Tôi đang cố gắng lấy tổng tích lũy của một biến (v) cho các nhóm ("a" và "b") trong một khung dữ liệu. Làm thế nào tôi có thể nhận được kết quả ở dưới cùng - có hàng thậm chí được đánh số đúng - vào cột cs của khung dữ liệu của tôi?Áp dụng chức năng cho các nhóm trong một data.frame trong R

> 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 

Tôi đoán tôi có thể tìm ra một số cách mất thời gian để lấy dữ liệu từ các khung dữ liệu đó vào d $ cs, nhưng cần phải có một số chỉnh sửa dễ dàng.

Trả lời

10

Tôi sẽ sử dụng ave. Nếu bạn nhìn vào nguồn của ave, bạn sẽ thấy nó về cơ bản kết thúc tốt đẹp của Martin Morgan solution.

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 
+0

Tôi luôn quên về 'ave'; mặc dù là như nhau đi như 2 khác? –

+0

@TylerRinker: về cơ bản nó giống như giải pháp của Martin (xem bản chỉnh sửa của tôi). –

+0

Tôi đã nhầm lẫn b/c tôi so với joran's. Tôi quên plyr sắp xếp lại mọi thứ. +1 –

7

công cụ của tôi về sự lựa chọn cho những việc này là plyr gói:

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 
13

split<- là một con quái vật khá lạ

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

dẫn đến

> 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

Đó chính là 'chia <-. Default'. Tôi đã không nhận ra nó tồn tại (hoặc đó là cơ sở cho ave.) 'Split <-. Data.frame' thậm chí còn lạ hơn. –

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 

Một giải pháp sử dụng bởi chức năng, nhưng tôi đã phải ra lệnh cho các dữ liệu đầu tiên

Các vấn đề liên quan