问题
This should be trivial to code but could not think of an elegant one-liner in R. I have a dataframe as below:
data <- data.frame( index= seq(1:20), event=rep(0,20) )
data$event[10] <- 1
data$event[15] <- 1
I simply want to add start
and stop
counter columns that increment in 10's and reset right after an event=1
is observed. So the desired output with these two additional columns would be:
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
Obviously, data$stop <- data$start + 10
but how can I apply()
the start
incrementation loigc as described?
回答1:
How about this:
Reduce(function(x,y) (1-y)*(x+10), data$event[-nrow(data)], accumulate=T, init=0)
回答2:
You could get your values with
data$start <- 10*(ave(
rep(0,nrow(data)),
cumsum(c(0, head(data$event,-1))),
FUN=seq_along)-1
)
data$end <- data$start + 10
Here we use cumsum
to track when events occur (but we need to shift them a step so the reset occurs after the event rather than at the event). And we use ave
within the groups to generate sequences per group.
回答3:
So unfortunately, the apply family of functions only replaces a for loop when the iterations of that loop do not depend on previous iterations.
You could write a for loop like:
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)
来源:https://stackoverflow.com/questions/27156082/r-conditional-incrementation