2013-02-09 58 views
1

改變這裏是我的一個小數據重複的例子:計算從數據基線長格式

> mydata <- structure(list(subject = c(1, 1, 1, 2, 2, 2), time = c(0, 1, 2, 0, 1, 2), measure = c(10, 12, 8, 7, 0, 0)), .Names = c("subject", "time", "measure"), row.names = c(NA, -6L), class = "data.frame") 

> mydata 

subject time measure 
1   0  10 
1   1  12 
1   2  8 
2   0  7 
2   1  0 
2   2  0 

我想產生一個新的變量是「基線的變化」。也就是說,我想

subject time measure change 
1   0  10  0 
1   1  12  2 
1   2  8  -2 
2   0  7  0 
2   1  0  -7 
2   2  0  -7 

是否有一個簡單的方法來做到這一點,除了通過所有的記錄循環編程或重塑以寬幅第一?

回答

3

什麼:

mydata$change <- do.call("c", with(mydata, lapply(split(measure, subject), function(x) x - x[1]))) 

或者你也可以使用ave功能:

with(mydata, ave(measure, subject, FUN=function(x) x - x[1])) 
# [1] 0 2 -2 0 -7 -7 

within(mydata, change <- ave(measure, subject, FUN=function(x) x - x[1])) 
# subject time measure change 
# 1  1 0  10  0 
# 2  1 1  12  2 
# 3  1 2  8  -2 
# 4  2 0  7  0 
# 5  2 1  0  -7 
# 6  2 2  0  -7 
4

有很多可能性。我的收藏夾:

library(plyr) 
ddply(mydata,.(subject),transform,change=measure-measure[1]) 

    subject time measure change 
1  1 0  10  0 
2  1 1  12  2 
3  1 2  8  -2 
4  2 0  7  0 
5  2 1  0  -7 
6  2 2  0  -7 

library(data.table) 
myDT <- as.data.table(mydata) 
myDT[,change:=measure-measure[1],by=subject] 
print(myDT) 

    subject time measure change 
1:  1 0  10  0 
2:  1 1  12  2 
3:  1 2  8  -2 
4:  2 0  7  0 
5:  2 1  0  -7 
6:  2 2  0  -7 

如果數據集很大,data.table更可取。

+0

@Arun我沒有做出小的數據集的聲明,不是嗎?雖然對於初學者來說data.table是一種很難掌握的東西,但最好還是繼續使用傳統的data.frames。 – Roland 2013-02-09 13:37:40

+0

@Arun我不知道它是否仍然如此,但是我記得使用'print'有一個性能優勢。無論如何,這是更好的語法。 – Roland 2013-02-09 13:39:04

+0

@Arun https://r-forge.r-project.org/tracker/index.php?func=detail&aid=1001&group_id=240&atid=978 – Roland 2013-02-09 13:53:12

1

可以tapply使用:

mydata$change<-as.vector(unlist(tapply(mydata$measure,mydata$subject,FUN=function(x){return (x-rep(x[1],length(x)))})));