如何解决为什么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
}
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
,因此,当期望NA
或TRUE
时,逻辑运算符将返回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}}和{}的长度的子集,并将其合并到布尔表达式中。 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 举报,一经查实,本站将立刻删除。