我想在SOG列中创建一个连续运行零的计数器。
对于SOG中第一个0的序列,将列中的计数器设置为1.对于第二轮零,设置'停止'到2,等等。
SOG Stops
--- -----
4 0
4 0
0 1
0 1
0 1
3 0
4 0
5 0
0 2
0 2
1 0
2 0
0 3
0 3
0 3
答案 0 :(得分:7)
SOG <- c(4,4,0,0,0,3,4,5,0,0,1,2,0,0,0)
#run length encoding:
tmp <- rle(SOG)
#turn values into logicals
tmp$values <- tmp$values == 0
#cumulative sum of TRUE values
tmp$values[tmp$values] <- cumsum(tmp$values[tmp$values])
#inverse the run length encoding
inverse.rle(tmp)
#[1] 0 0 1 1 1 0 0 0 2 2 0 0 3 3 3
答案 1 :(得分:3)
尝试
df$stops<- with(df, cumsum(c(0, diff(!SOG))>0)*!SOG)
df$stops
# [1] 0 0 1 1 1 0 0 0 2 2 0 0 3 3 3
答案 2 :(得分:2)
使用dplyr
:
library(dplyr)
df <- df %>% mutate(Stops = ifelse(SOG == 0, yes = cumsum(c(0, diff(!SOG) > 0)), no = 0))
df$Stops
#[1] 0 1 1 1 0 0 0 2 2 0 0 3 3 3
编辑:除了我们这些仍然是初学者的人之外,这个问题的许多答案都使用了逻辑(即TRUE,FALSE)。在!
之类的数字变量之前SOG
测试值是0
,如果是,则分配TRUE
,否则分配FALSE
。
SOG
#[1] 4 0 0 0 3 4 5 0 0 1 2 0 0 0
!SOG
#[1] FALSE TRUE TRUE TRUE FALSE FALSE FALSE TRUE TRUE FALSE FALSE
#[12] TRUE TRUE TRUE
diff()
取值和前面的值之间的差值。请注意,此列表中的元素少于SOG
中的元素,因为第一个元素没有用于计算差异的滞后。在逻辑方面,diff(!SOG)
会为1
,TRUE - FALSE = 1
和FALSE - TRUE = -1
生成0
。
diff(SOG)
#[1] -4 0 0 3 1 1 -5 0 1 1 -2 0 0
diff(!SOG)
#[1] 1 0 0 -1 0 0 1 0 -1 0 1 0 0
所以cumsum(diff(!SOG) > 0)
只关注TRUE - FALSE
更改
cumsum(diff(!SOG) > 0)
#[1] 1 1 1 1 1 1 2 2 2 2 3 3 3
但由于差异列表是一个较短的元素,我们可以附加一个元素:
cumsum(c(0, diff(!SOG) > 0)) #Or cumsum( c(0, diff(!SOG)) > 0 )
#[1] 0 1 1 1 1 1 1 2 2 2 2 3 3 3
然后将!SOG
的列表“乘以”@akrun
的答案,或使用ifelse()
命令。如果是SOG == 0
的特定元素,我们会使用cumsum(c(0, diff(!SOG) > 0))
中的相应元素;如果不是0
,我们会指定0
。
答案 3 :(得分:1)
带有 rle
的单行是 -
df <- data.frame(SOG = c(4,4,0,0,0,3,4,5,0,0,1,2,0,0,0))
df <- transform(df, Stops = with(rle(SOG == 0), rep(cumsum(values) * values, lengths)))
df
# SOG Stops
#1 4 0
#2 4 0
#3 0 1
#4 0 1
#5 0 1
#6 3 0
#7 4 0
#8 5 0
#9 0 2
#10 0 2
#11 1 0
#12 2 0
#13 0 3
#14 0 3
#15 0 3