2017-09-21 45 views
1

我有一个大量的车祸数据,它的一个样本提供如下。cumsum根据某些限制在r

  • accident是事故发生的二元变量还是不是 。
  • shift_number是换档次数,0表示驾驶员是 休息而不是换班。
  • time_diff是每次观察的时间量。

    df <- data.frame(
    accident  = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1), 
    shift_number = c(1, 1, 0, 0, 0, 2, 2, 2, 0, 0, 3, 3, 3, 3, 3), 
    time_diff = 3:17 
    ) 
    

我的问题是,因为驾驶员开始这种转变对于每次事故来衡量工作时间的总量。

wanted <- data.frame 
(
    accident  = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1), 
    shift_number = c(1, 1, 0, 0, 0, 2, 2, 2, 0, 0, 3, 3, 3, 3, 3), 
    time_diff = 3:17, 
    cum_time  = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 75) 
) 

有没有人有解决R问题的想法?因为我有大量的数据需要处理,所以最好有data.table或vectorised解决方案。

+0

我不清楚'cum_time'是如何计算的。 –

+0

@Ronak Shah cum_time每次事故都是在该班次开始时的“time_diff”cumsum,事故实际发生的地点 –

回答

3
df$cum_time = 0 
accident = which(df$accident == 1) 

df$cum_time[accident] <- sapply(accident, function(x) { 
    sum(df$time_diff[(which.max(cumsum(df$shift_number[1:x] == 0)) + 1): x]) 
}) 

df 

# accident shift_number time_diff cum_time 
#1   0   1   3  0 
#2   0   1   4  0 
#3   0   0   5  0 
#4   0   0   6  0 
#5   0   0   7  0 
#6   0   2   8  0 
#7   0   2   9  0 
#8   0   2  10  0 
#9   0   0  11  0 
#10  0   0  12  0 
#11  0   3  13  0 
#12  1   3  14  27 
#13  0   3  15  0 
#14  0   3  16  0 
#15  1   3  17  75 

我们首先让所有的值cum_time变量为0。我们发现,在发生accident指数。对于这些指数中的每一个,我们在shift_number中找到最新的0并且计算从最近的0到xtime_diff的值的总和,并将其分配给其各自的指数。

0

使用ave功能通过shift_number计算的time_diff累计总和:

cumsum_by_shift <- ave(df$time_diff, df$shift_number, FUN=cumsum) 
#[1] 3 7 5 11 18 8 17 27 29 41 13 27 42 58 75 

挑选出其中发生事故的cumsum_by_shift元素:

cum_time <- ifelse(df$accident == 1, cumsum_by_shift, 0) 
#[1] 0 0 0 0 0 0 0 0 0 0 0 27 0 0 75 

注意使用矢量ifelse功能。

+0

好的想法,但我认为你在这里错过了一些东西。尝试做'df $ shift_number [14] < - 0'并重新计算'cum_time'。 –

+0

@RonakShah此代码的工作原理是每次休息后移位数增加,即如果'df $ shift_number [14]'为'0',则下一个非零移位数应该为'4'。 –