帮助rle命令

时间:2011-05-16 05:32:48

标签: r

我在使用rle命令时遇到了一些麻烦,该命令旨在找到参与者连续达到8个连续点的位置。

例如,如果:

x <- c(0,1,0,1,1,1,1,1,1,1,1,1)

我想返回值11。

感谢DWin,我一直在使用这段代码:

which( rle(x2)$values==1 & rle(x2)$lengths >= 8)
sum(rle(x)$lengths[ 1:(min(which(rle(x)$lengths >= 8))-1) ]) + 8

我一直在成功使用此代码来处理我的数据。但是,我注意到在处理我的一个数据文件时出错了。

例如,如果

 x <- c(1,1,1,1,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)

代码返回19,这是达到一行中八个连续零的点。我不确定出了什么问题或者它是如何解决的。

提前感谢您的帮助。

威尔

3 个答案:

答案 0 :(得分:10)

您需要将第一行代码完整地粘贴到第二行:

sum(rle(x)$lengths[ 1:(min(which( rle(x2)$values==1 & rle(x2)$lengths >= 8))-1) ]) + 8
[1] 39

但是,这是使用函数filter的另一种方法。这产生了与我认为更易读的代码相同的结果:

which(filter(x2, rep(1/8, 8), sides=1) == 1)[1]
[1] 39

以这种方式使用时,filter函数基本上计算向量中8个值的块上的移动平均值。然后我返回移动平均值等于1的第一个值的位置。

答案 1 :(得分:8)

在我教的基础程序设计课程中,我建议学生给子结构命名,并检查这些子结果:

lengthOfrepeatsOfAnything<-rle(x)$lengths
#4  2  5 11  2  2  3  2 17
whichRepeatsAreOfOnes<-rle(x)$values==1
#1 3 5 7 9
repeatsOfOnesLength<-lengthOfrepeatsOfAnything * whichRepeatsAreOfOnes #TRUE = 1, FALSE=0
#4  0  5  0  2  0  3  0 17
whichRepeatOfOneAreLongerThanEight<-which(repeatsOfOnesLength >= 8)
#9
result<-NA
if(length(whichRepeatOfOneAreLongerThanEight)>0){
    firstRepeatOfOneAreLongerThanEight<-whichRepeatOfOneAreLongerThanEight[1]
    #9
    if(firstRepeatOfOneAreLongerThanEight==1){
        result<-8
    }
    else{
        repeatsBeforeFirstEightOnes<-1:(firstRepeatOfOneAreLongerThanEight-1)
        #1 2 3 4 5 6 7 8
        lengthsOfRepeatsBeforeFirstEightOnes<-lengthOfrepeatsOfAnything[repeatsBeforeFirstEightOnes]
        #4  2  5 11  2  2  3  2
        result<-sum(lengthsOfRepeatsBeforeFirstEightOnes) + 8
    }
}

我知道它看起来并不像在线解决方案那么花哨,但它有助于使事情变得清晰并发现错误......此外:如果你在4个月内回顾这段代码怎么办?哪一个会更容易理解?

答案 2 :(得分:1)

我的建议是将代码分解为更简单的部分。正如@Nick所建议的那样,您希望编写可以轻松调试的代码,并且模块化编码可以让您这样做。

# find runs of 0s and 1s
run_01 = rle(x)

# find run of 1's with length >=8
run_1 = with(run_01, which(values == 1 & lengths >=8))

# find starting position of run_1
start_pos = sum(run_01$lengths[1:(run_1 - 1)])

# add 8 to it
end_pos  = start_pos + 8