微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么R请求额外的TRUE / FALSE

如何解决为什么R请求额外的TRUE / FALSE

我正在尝试计算随机生成的DNA链中ATG密码子的数量并创建直方图:

s1 = makednA(500)    
count = 0
n = 100
totCount = vector("numeric",n)
for(j in 1:n){
  s1 = makednA(500) 
  count = 0
  for(i in 1:500){
    if(s1[i] == "A" & s1[i+1] == "T" & s1[i+2] == "G"){
      count = count + 1
    }
  }
  totCount[j] = count
}

当我运行此代码时,R给出以下错误

Show in New WindowClear OutputExpand/Collapse Output
Error in if (s1[i] == "A" & s1[i + 1] == "T" & s1[i + 2] == "G") { : 
  missing value where TRUE/FALSE needed

解决方法

问题出在此代码中:

for(i in 1:500){
    if(s1[i] == "A" & s1[i+1] == "T" & s1[i+2] == "G"){
      count = count + 1
    }

i == 499时,则i + 2 == 501。对象s1只有500个元素。没有第501个元素,因此R返回NA。什么都不等于NA,甚至不等于NA,因此,当期望NATRUE时,逻辑运算符将返回FALSE。修改以下内容,您应该会很好。

for(i in 1:498){
        if(s1[i] == "A" & s1[i+1] == "T" & s1[i+2] == "G"){
          count = count + 1
        }
,

Ben Norris' answer很好地说明了导致#include <iostream> int main() { int array[] = { 0,1,2,3,4,5,6,7,8,9 }; int* pArray = array; while (pArray < (array + 10)) { // Compare to the 'original' value plus 10! std::cout << *pArray << " "; pArray++; } return 0; } 循环错误的原因以及如何避免该错误。

但是,for循环可以由矢量化代码代替,该矢量化代码在许多用例中效率更高。性能或执行速度可能会成为基因组数据量的问题。

这里有两个向量化的替代方法,它们比最里面的for循环要快得多(并且需要更少的编码)。我已经对其他一些方法进行了基准测试,但是这两种方法是最快的。

OP的for循环

for

已对代码进行参数化以研究各种问题的大小。 OP尚未发布m <- 500L s1 <- makeDNA(m) count <- 0L for(i in seq_len(m-2L)) { if(s1[i] == "A" & s1[i+1] == "T" & s1[i+2] == "G") { count <- count + 1L } } 的代码,因此我编写了自己的代码:

makeDNA()

第一种选择:子集,移位和总和

这里,从makeDNA <- function(n) sample(c("A","T","G"),n,TRUE) 中选取三个分别长于{1,{1}}和{enter image description here}的长度的子集,并将其合并到布尔表达式中。 m - 2L对在所得逻辑向量中所有s1的出现进行计数:

sum()

第二种选择:字符串操作

TRUE

在这里,字符向量折叠为单个字符串。然后,计算字符串中“ ATG”的出现次数。 s1 <- makeDNA(m) sum(s1[1:(m-2L)] == "A" & s1[2:(m-1L)] == "T" & s1[3:m] == "G") 包用于字符串操作。另外,管道还可以提高可读性。

基准

为了进行基准测试,字符向量的长度library(magrittr) s1 <- makeDNA(m) stringi::stri_join(s1,collapse = "") %>% stringi::stri_count_fixed("ATG") 和重复次数stringi都会变化。对于向量化变体,外部m循环由n函数代替。 for自动检查所有3个表达式的结果是否相等。

replicate()

可以绘制基准测试结果

bench()

{{3}}

library(magrittr) library(bench) bm <- press( n = c(10L,100L,1000L),m = c(50L,500L,5000L),{ mark( loop = { set.seed(123) totCount = vector("integer",n) for(j in 1:n) { s1 <- makeDNA(m) count <- 0L for(i in seq_len(m-2L)) { if(s1[i] == "A" & s1[i+1] == "T" & s1[i+2] == "G") { count <- count + 1L } } totCount[j] <- count } totCount },subset = { set.seed(123) replicate(n,{ s1 <- makeDNA(m) sum(s1[1:(m-2L)] == "A" & s1[2:(m-1L)] == "T" & s1[3:m] == "G") }) },stringi = { set.seed(123) replicate(n,{ s1 <- makeDNA(m) stringi::stri_join(s1,collapse = "") %>% stringi::stri_count_fixed("ATG") }) } ) } ) 循环几乎总是最慢,而子集几乎总是最快。对于OP在library(ggplot2) autoplot(bm) 中的用例,子集比for循环快20倍以上。

对于较大的m == 500L,字符串操作与子设置相同(或稍稍领先)。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。