r - 嵌套在for循环中的if语句在R中不起作用?
问题描述
threshold <- .3
l <- list()
for(i in 1:length(mitochondrial_genes)) {
if(i < length(mitochondrial_genes)) {
for(j in (i+1) : length(mitochondrial_genes)) {
a <- cor.test(mitochondrial_genes[,i], mitochondrial_genes[,j])
if(grepl("*",names(mitochondrial_genes)[i])|grepl("*",names(mitochondrial_genes)[j])) {
if(a$estimate > threshold){
l <- c(l, list(c(names(mitochondrial_genes)[i], names(mitochondrial_genes)[j],a$estimate)))
}
}
}
}
}
线粒体基因是一个大数据集,由代表基因的列组成。一些基因名称(列名)旁边有 * 符号。我本质上想返回一个满足相关性测试最小阈值的基因对列表。
代码成功运行,但它生成了所有可能的对,而不仅仅是那些至少有一个基因名称旁边带有 * 的基因对。基本上,这部分代码似乎是问题所在:
if(grepl("*",names(mitochondrial_genes)[i])|grepl("*",names(mitochondrial_genes)[j]))
我做错什么了吗?当我在终端上测试 if 语句时,它是孤立地工作的,并且代码似乎正在生成所有对,而不是根据令人困惑的 if 语句过滤它们。
这是一个线粒体基因的例子。
解决方案
列选择问题是由于您的正则表达式模式。这与正则表达式密切相关,以选择以 A 开头的字符串,不包含星号或井号,尽管在该问题*
中它既是倒置的(不存在与存在),也是许多规则之一。
在这种情况下,有两种选择:
### wrong
grepl("*", c("a","a*"))
# [1] TRUE TRUE
### right
grepl("\\*", c("a","a*"))
# [1] FALSE TRUE
grepl("[*]", c("a","a*"))
# [1] FALSE TRUE
解释:
*
在正则表达式中的意思是“零个或多个”,但更重要的是…… “前面的字符/类/组”;将此与+
表示“一个或多个”进行比较,也需要在前面加上一些东西- 通常,正则表达式中的“任何东西”用 表示
.*
,其中.
表示“任何字符”,*
仍然表示 0 或更多 - 因为你想要文字星号,你要么需要转义它(
\\*
在 R 中),要么让它成为一个 class[*]
,其中括号内的大多数特殊字符失去了它们的含义(例外:^
,-
, 并且]
可以按字面意思包含,但需要完成照顾和限制)
还有一些其他注意事项:
您对每一对都运行测试,即使您只想要其中至少一个名称作为星号的那些;效率低下,如果您的数据“很大”,那么这只是在浪费时间(和资源);最好在运行测试之前确定要执行哪些测试
不要在语句中使用
|
or ,只使用or ; 原因:&
if
||
&&
|
/对长度为 0 或更大的&
逻辑向量进行操作,而if
需要恰好长度为 1;如果你使用这些向量变体,那么你真的应该在条件向量和;之间使用any
、all
或其他一些聚合函数。if
如果你的条件是长度为 1,那么在你的编程风格中是声明性的,并使用 always-length-1
and
/or
操作符,&&
并且||
;有条件的短路:
&&
/||
支持它,&
/|
不要......试试这个看看这意味着什么:TRUE || stop("oops") TRUE | stop("oops")
combn
我通过使用以下内容并过滤可能的组合来修复第一个项目符号。第二,我在向量上|
正确使用(不是在if
语句中),if
不需要。
您的示例数据图像(请提供可用的东西,而不是图像)不代表您的意思(*
名称中没有),因此我将生成一些假数据并运行假测试来演示配对机制。
set.seed(42)
dat <- data.frame(a1=runif(5), b1=runif(5), "a1*"=runif(5), "b1*"=runif(5), check.names=FALSE)
dat
# a1 b1 a1* b1*
# 1 0.915 0.519 0.458 0.940
# 2 0.937 0.737 0.719 0.978
# 3 0.286 0.135 0.935 0.117
# 4 0.830 0.657 0.255 0.475
# 5 0.642 0.705 0.462 0.560
(在combn
这里使用效果很好,因为测试是对称的:cor.test(a, b)
与 相同cor.test(b, a)
。如果测试是定向/不对称的,那么可以使用expand.grid(names(dat), names(dat))
。)
这是预定义配对的一种方法:
pairs <- as.data.frame(t(combn(names(dat), 2)))
pairs
# V1 V2
# 1 a1 b1
# 2 a1 a1*
# 3 a1 b1*
# 4 b1 a1*
# 5 b1 b1*
# 6 a1* b1*
pairs <- pairs[grepl("[*]", pairs$V1) | grepl("[*]", pairs$V2),]
pairs
# V1 V2
# 2 a1 a1*
# 3 a1 b1*
# 4 b1 a1*
# 5 b1 b1*
# 6 a1* b1*
现在我们可以运行测试:
pairs$estimate <- mapply(function(i, j) cor.test(dat[,i], dat[,j])$estimate,
pairs$V1, pairs$V2)
pairs
# V1 V2 estimate
# 2 a1 a1* -0.611
# 3 a1 b1* 0.901
# 4 b1 a1* -0.655
# 5 b1 b1* 0.685
# 6 a1* b1* -0.303
threshold <- 0.3
pairs[pairs$estimate > threshold, ]
# V1 V2 estimate
# 3 a1 b1* 0.901
# 5 b1 b1* 0.685
推荐阅读
- ruby-on-rails - 数组在另一个数组中出现了多少次?
- javascript - 为作为参数传递给Javascript函数的对象分配别名
- angular - 如何在表(mat-table)中检查所有或取消检查使用(mat-checkbox)
- python - 在 win32file.DeviceIoControl 上解压结构
- c# - C# linq 删除集合中的所有元素 OfType
- node.js - 卷曲 -d 与 --data-binary
- angularjs - Ionic FabricJs 访问函数的问题
- opencv - AVFrame 到 OpenCV:Mat 与 GpuMat
- python - 使用多个过滤条件从较大的数据帧创建较小的数据帧:使用 python 和 pandas
- nlp - spacy 将 conllul 转换为 spacy json 格式