我有一系列事件,编码为A,B和C.对于每个元素,我需要计算此元素之前重复的次数,但如果不重复,则每行的计数器应减少一次。在每个项目的第一次遇到时,它的计数器为零。例如:
x<-c('A','A','A','B','C','C','A','B','A','C')
y<-c(0,1,2,0,0,1,-2,-4,-4,-3)
cbind(x,y)
x y
[1,] "A" "0"
[2,] "A" "1"
[3,] "A" "2"
[4,] "B" "0"
[5,] "C" "0"
[6,] "C" "1"
[7,] "A" "-2"
[8,] "B" "-4"
[9,] "A" "-4"
[10,] "C" "-3"
我需要从x生成列y。我知道我可以使用rle
来获取游程长度,但是我不知道如何从特定事件的最后一次遭遇开始计算减少时间。
答案 0 :(得分:2)
我认为这是解决问题的R
方法。我们可以用同样的方式计算x
中所有不同元素的索引,将其偏移到初始位置然后将它们组合在一起。
分别为x:
中的每个唯一元素计算索引library(data.table)
sepIndex <- lapply(unique(x), function(i) {
s = cumsum(ifelse(duplicated(rleid(x == i)) & x == i, 1, -1)) + min(which(x == i));
# use `rleid` with `duplicated` to find out the duplicated elements in each block.
# and assign `1` to each duplicated element and `-1` otherwise and use cumsum for cumulative index
# offset the index by the initial position of the element `min(which(x == i))`
replace(s, x != i, NA)
})
它为我们提供了每个唯一元素的索引列表:
sepIndex
# [[1]]
# [1] 0 1 2 NA NA NA -2 NA -4 NA
# [[2]]
# [1] NA NA NA 0 NA NA NA -4 NA NA
# [[3]]
# [1] NA NA NA NA 0 1 NA NA NA -3
使用Reduce
函数将列表合并为一个应该为您提供所需的内容:
Reduce(function(x, y) ifelse(is.na(x), y, x), sepIndex)
# [1] 0 1 2 0 0 1 -2 -4 -4 -3
答案 1 :(得分:1)
使用基础R还有另一种方式
positions <- sapply(unique(x),function(t) which(x %in% t))
values <- sapply(sapply(positions,diff),function(s) c(0,cumsum(ifelse(s>1,-s,s))))
df <- data.frame(positions=unlist(positions),values=unlist(values))
df[with(df,order(positions)),2]