2015-10-04 176 views
2

我的數據如下所示。 每個id已被觀察了幾次。 main是每次觀察的結果。R增量 - 避免循環

我需要做的是每增加一次main已經改變,所以每次觀察結果都與前一次不同。

因此,例如,id第一個觀察結果是20然後30然後連續12

> dtd 
    id main ep 
1 1 20 1 
2 1 30 1 
3 1 12 1 
4 1 12 1 
5 1 12 1 
6 1 15 1 
7 1 15 1 
8 2 30 1 
9 2 12 1 
10 2 12 1 
11 2 23 1 
12 2 23 1 

我需要的到底是什麼

> dtd 
    id main ep 
1 1 20 1 
2 1 30 2 
3 1 12 3 
4 1 12 3 
5 1 12 3 
6 1 15 4 
7 1 15 4 
8 2 30 1 
9 2 12 2 
10 2 12 2 
11 2 23 3 
12 2 23 3 

所以每個有每個id更改時遞增。

任何建議非常歡迎。

我想出了這個循環,但它非常繁瑣。

for(i in 2:nrow(dtd)){ 
    if(dtd$id[i] == dtd$id[i-1] & dtd$main[i] != dtd$main[i-1]){ 
    dtd$ep[i] = dtd$ep[i-1] + 1 
} 
    if(dtd$id[i] == dtd$id[i-1] & dtd$main[i] == dtd$main[i-1]){ 
    dtd$ep[i] = dtd$ep[i-1] 
    } 
} 

感謝

數據

dtd <- structure(list(id = c(1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2), main = c(20, 
    30, 12, 12, 12, 15, 15, 30, 12, 12, 23, 23), ep = c(1, 2, 3, 
    3, 3, 4, 4, 1, 2, 2, 3, 3)), .Names = c("id", "main", "ep"), row.names = 
    c(NA, -12L), class = "data.frame") 

回答

4

您可以使用ave

DF$ep <- ave(DF$main, DF$id, FUN = function(x) cumsum(c(1L, diff(x) != 0))) 

這給

id main ep 
1 1 20 1 
2 1 30 2 
3 1 12 3 
4 1 12 3 
5 1 12 3 
6 1 15 4 
7 1 15 4 
8 2 30 1 
9 2 12 2 
10 2 12 2 
11 2 23 3 
12 2 23 3 

我發現cumsumdiff很難與和調試工作,所以我會改用

library(data.table) 
setDT(DF)[, ep := rleid(main), by=id] 

這給

id main ep 
1: 1 20 1 
2: 1 30 2 
3: 1 12 3 
4: 1 12 3 
5: 1 12 3 
6: 1 15 4 
7: 1 15 4 
8: 2 30 1 
9: 2 12 2 
10: 2 12 2 
11: 2 23 3 
12: 2 23 3