在向量中找到相同模式的长度

时间:2014-08-19 11:53:09

标签: r function which

我有这样的矢量

t<-c(9,9,9,9,9,9,10,10,10,10,8,8,8,8,8,200,8,8,7,9,9,9,9,9)

我想得到的是每次运行相同字符的每个开始和结束的索引。取9.输出将是1到6和20到24.对于7,它将只有19.有没有办法编写一个函数,在其中输入特定的数字(如9或7),然后只输出R?

中概述的不明印迹

4 个答案:

答案 0 :(得分:1)

使用基本编程方法和简单的可调代码。基数R可能会有所帮助:

t<-c(9,9,9,9,9,9,10,10,10,10,8,8,8,8,8,200,8,8,7,9,9,9,9,9)
i = 1; j=1
while(!is.na(t[i+2])){
    while(t[i]==t[i+1]) {i=i+1; if(is.na(t[i+1]))break; }
    i=i+1
    cat("number=",t[i-1],"times=",(i-j),"start=",j,"end=",i-1,'\n')
    j = i
}

number= 9 times= 6 start= 1 end= 6 
number= 10 times= 4 start= 7 end= 10 
number= 8 times= 5 start= 11 end= 15 
number= 200 times= 1 start= 16 end= 16 
number= 8 times= 2 start= 17 end= 18 
number= 7 times= 1 start= 19 end= 19 
number= 9 times= 5 start= 20 end= 24 

获取数据框:

outdf = data.frame(number=numeric(), start=numeric(), end=numeric(), times=numeric())
i = 1; j=1
while(!is.na(t[i+2])){
    while(t[i]==t[i+1]) {i=i+1; if(is.na(t[i+1]))break; }
    i=i+1
    outdf[nrow(outdf)+1,] = c(t[i-1], j, i-1, i-j)
    j = i
}
outdf
  number start end times
1      9     1   6     6
2     10     7  10     4
3      8    11  15     5
4    200    16  16     1
5      8    17  18     2
6      7    19  19     1
7      9    20  24     5

对于一个数字的函数:

myfn = function(num){
    outdf = data.frame(number=numeric(), start=numeric(), end=numeric(), times=numeric())
    i = 1; j=1
    while(!is.na(t[i+2])){
        while(t[i]==t[i+1]) {i=i+1; if(is.na(t[i+1]))break; }
        i=i+1
        if(t[i-1]==num) {outdf[nrow(outdf)+1,] = c(t[i-1], j, i-1, i-j)}
        j = i
    }
    outdf
}

myfn(10)
  number start end times
1     10     7  10     4

myfn(9)
  number start end times
1      9     1   6     6
2      9    20  24     5

myfn(8)
  number start end times
1      8    11  15     5
2      8    17  18     2

编辑:正如beginneR和Carl Witthoft在评论中所建议的那样:

rle(t)
Run Length Encoding
  lengths: int [1:7] 6 4 5 1 2 1 5
  values : num [1:7] 9 10 8 200 8 7 9

但这里的输出有点神秘。

答案 1 :(得分:1)

正如beginneR所说,只需使用rle即可。输出为您提供每次值变化的起点,因此很容易计算出运行位置。

 t<-c(9,9,9,9,9,9,10,10,10,10,8,8,8,8,8,200,8,8,7,9,9,9,9,9)
 rlet<-rle(t)
 rlet
Run Length Encoding
  lengths: int [1:7] 6 4 5 1 2 1 5
  values : num [1:7] 9 10 8 200 8 7 9

只需将lengths值汇总到values==9的每个实例,依此类推。

答案 2 :(得分:1)

以下是rle解决方案

f <- function(t, n) {
    x <- rle(t)
    i <- x$values == n
    end.pos <- cumsum(x$lengths)[i]
    start.pos <- end.pos - x$lengths[i] + 1
    data.frame(from = start.pos, to = end.pos)
}

t <- c(9,9,9,9,9,9,10,10,10,10,8,8,8,8,8,200,8,8,7,9,9,9,9,9)
f(t, 9)  
#  from to
#     1  6
#    20 24
f(t, 7)
#  from to
#    19 19

您可以修改f的返回值,以获得所需格式的输出。

或者,将whichdiff一起使用,从而提供更好的效果

f2 <- function(t, n) {
    i <- which(t == n)
    start.i <- c(0, which(diff(i) != 1)) + 1
    end.i <- c(start.i[-1] - 1, length(i))
    data.frame(from = i[start.i], to = i[end.i])
}

比较表现:

tt <- rep(t, 100)
library(microbenchmark)
microbenchmark(f = f(tt, 9), f2 = f2(tt, 9))
# Unit: microseconds
# expr     min       lq   median       uq      max neval
#    f 578.733 582.0575 584.7530 594.4130 1177.366   100
#   f2 350.153 354.1275 358.5175 378.0135 1186.022   100

答案 3 :(得分:0)

你可以做点什么

bool started = false;
int start = -1;
int end = -1;
for(i in t.length) :
    if(t[i]==wantedNumber) started = true ; start = i ;
    else if (started && t[i]!=wantedNumber) end = i ; break;