计算元素在序列中重复或不重复的次数(R)

时间:2016-07-06 14:28:25

标签: r sequence

我有一系列事件,编码为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来获取游程长度,但是我不知道如何从特定事件的最后一次遭遇开始计算减少时间。

2 个答案:

答案 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]