2015-10-04 143 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