【问题标题】:compare adjacent elements of the same vector (avoiding loops)比较同一向量的相邻元素(避免循环)
【发布时间】:2011-10-20 18:52:09
【问题描述】:

我设法写了一个for loop 来比较以下向量中的字母:

bases <- c("G","C","A","T")
test <- sample(bases, replace=T, 20)

test 将返回

[1] "T" "G" "T" "G" "C" "A" "A" "G" "A" "C" "A" "T" "T" "T" "T" "C" "A" "G" "G" "C"

使用函数Comp()我可以检查一个字母是否与下一个字母匹配

Comp <- function(data)
{
    output <- vector()
    for(i in 1:(length(data)-1))
    {
    if(data[i]==data[i+1])
        {
        output[i] <-1
        }
        else
        {
        output[i] <-0
        }
    }
    return(output)
}

导致;

> Comp(test)
 [1] 0 0 0 0 0 1 0 0 0 0 0 1 1 1 0 0 0 1 0

这是有效的,但是对于大量数字来说它非常慢。为此我尝试了sapply()

Comp <- function(x,i) if(x[i]==x[i+1]) 1 else 0
unlist(lapply(test, Comp, test))

不幸的是,它不起作用... (Error in i + 1 : non-numeric argument to binary operator) 我无法弄清楚如何访问向量中的前一个字母以进行比较。 length(data)-1,“不比较”最后一个字母可能会成为问题。

谢谢大家的帮助!

干杯 幸运

【问题讨论】:

  • 我改写了标题以更好地说明问题并供参考。您还应该知道 sapply/lapply 等 循环,尽管形式不同。另见stackoverflow.com/questions/2275896/…
  • 谢谢,我是 R 和编程新手,对术语不太熟悉

标签: r vector string-comparison sapply


【解决方案1】:

只需“滞后”test 并使用矢量化的==

bases <- c("G","C","A","T")
set.seed(21)
test <- sample(bases, replace=TRUE, 20)
lag.test <- c(tail(test,-1),NA)
#lag.test <- c(NA,head(test,-1))
test == lag.test

更新:

另外,你的Comp 函数很慢,因为你在初始化它时没有指定output 的长度。我怀疑您正在尝试预分配,但vector() 创建了一个长度为零的向量,必须在循环的每次迭代期间扩展该向量。如果您将对vector() 的调用更改为vector(length=NROW(data)-1),您的Comp 函数会明显更快。

set.seed(21)
test <- sample(bases, replace=T, 1e5)
system.time(orig <- Comp(test))
#    user  system elapsed 
#  34.760   0.010  34.884 
system.time(prealloc <- Comp.prealloc(test))
#    user  system elapsed 
#    1.18    0.00    1.19 
identical(orig, prealloc)
# [1] TRUE

【讨论】:

    【解决方案2】:

    正如@Joshua 所写,您当然应该使用矢量化——它的效率更高。 ...但仅供参考,您的Comp 功能仍然可以优化一点。

    比较的结果是TRUE/FALSE,它是1/0 的美化版本。此外,确保结果是整数而不是数字会消耗一半的内存。

    Comp.opt <- function(data)
    {
        output <- integer(length(data)-1L)
        for(i in seq_along(output))
        {
            output[[i]] <- (data[[i]]==data[[i+1L]])
        }
        return(output)
    }
    

    ...还有速度差:

    > system.time(orig <- Comp(test))
       user  system elapsed 
      21.10    0.00   21.11 
    > system.time(prealloc <- Comp.prealloc(test))
       user  system elapsed 
       0.49    0.00    0.49 
    > system.time(opt <- Comp.opt(test))
       user  system elapsed 
       0.41    0.00    0.40 
    > all.equal(opt, orig) # opt is integer, orig is double
    [1] TRUE
    

    【讨论】:

    • 感谢您的建议!
    【解决方案3】:

    看看这个:

    > x = c("T", "G", "T", "G", "G","T","T","T")
    > 
    > res = sequence(rle(x)$lengths)-1
    > 
    > dt = data.frame(x,res)
    > 
    > dt
      x res
    1 T   0
    2 G   0
    3 T   0
    4 G   0
    5 G   1
    6 T   0
    7 T   1
    8 T   2
    

    可能工作得更快。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-05
      • 1970-01-01
      • 2017-03-15
      • 1970-01-01
      • 2023-03-09
      • 2014-12-17
      • 1970-01-01
      • 2012-05-04
      相关资源
      最近更新 更多