这对代码来说应该是微不足道的,但却无法想到R中优雅的单行代码。我有一个如下数据框:
data <- data.frame( index= seq(1:20), event=rep(0,20) )
data$event[10] <- 1
data$event[15] <- 1
我只想添加在{10}中递增的start
和stop
个计数器列,并在观察到event=1
后立即重置。因此,这两个附加列的所需输出将是:
index event start stop
1 1 0 0 10
2 2 0 10 20
3 3 0 20 30
4 4 0 30 40
5 5 0 40 50
6 6 0 50 60
7 7 0 60 70
8 8 0 70 80
9 9 0 80 90
10 10 1 90 100
11 11 0 0 10
12 12 0 10 20
13 13 0 20 30
14 14 0 30 40
15 15 1 40 50
16 16 0 0 10
17 17 0 10 20
18 18 0 20 30
19 19 0 30 40
20 20 0 40 50
显然,data$stop <- data$start + 10
但我如何apply()
start
增加loigc如上所述?
答案 0 :(得分:7)
这个怎么样:
Reduce(function(x,y) (1-y)*(x+10), data$event[-nrow(data)], accumulate=T, init=0)
答案 1 :(得分:4)
您可以使用
获取您的值data$start <- 10*(ave(
rep(0,nrow(data)),
cumsum(c(0, head(data$event,-1))),
FUN=seq_along)-1
)
data$end <- data$start + 10
这里我们使用cumsum
来跟踪事件发生的时间(但我们需要将它们移动一步,以便在事件之后而不是在事件处发生重置)。我们在组内使用ave
来生成每个组的序列。
答案 2 :(得分:2)
所以遗憾的是,当该循环的迭代不依赖于先前的迭代时,apply系列函数仅替换for循环。
你可以写一个for循环,如:
data <- data.frame( index= seq(1:20), event=rep(0,20) )
data$event[10] <- 1
data$event[15] <- 1
print(data)
data$start = rep(0, 20)
for(i in 2:20){
if(data$event[i] == 1){
data$start[i] = 0
} else data$start[i] = data$start[i-1] + 10
}
data$stop = data$start+10
print(data)