上下文
我最近问过这个问题:
Comparing partitions from split() using a nested for loop containing an if statement
其中我需要使用@robertdj提供的代码修复,根据距离矩阵比较split()
生成的分区
set.seed(1234) # set random seed for reproducibility
# generate random normal variates
x <- rnorm(5)
y <- rnorm(5)
df <- data.frame(x, y) # merge vectors into dataframe
d <- dist(x) # generate distance matrix
splt <- split(d, 1:5) # split data with 5 values in each partition
for (i in 1:length(splt)) {
for (j in 1:length(splt)) {
if (i != j) {
a <- length(which(splt[[i]] >= min(splt[[j]]))) / length(splt[[i]])
b <- length(which(splt[[j]] <= max(splt[[i]]))) / length(splt[[j]])
}
}
}
我生成了一个MWE,其中每个分割包含相同数量的元素。我这样做只是为了说明的目的,完全知道这不一定适用于真实的数据。
按照罗伯特·哈肯的评论,如果我这样做的话
d <- na.omit(d[lower.tri(d)])
我得到了长度不等的分区。
真实的数据
然而,我的真实的数据没有“相同大小”的属性。我的真实数据包含的分区比我的MWE中只有5个多得多。
这是我的代码
splt <- split(dist_matrix, sub("(?:(.*)\\|){2}(\\w+)\\|(\\w+)\\|.*?$", "\\1-\\2", colnames(dist_matrix)))
距离矩阵dist_matrix
包含FASTA标头,我从中提取了物种名称。
然后我在双重嵌套循环中使用上面的splt
。
例如,splt[[4]]
包含5个值,而splt[[10]]
包含9个值。
splt[[4]]
[1] 0.1316667 0.1383333 0.1166667 0.1333333 0.1216667
splt[[10]]
[1] 0.1450000 0.1483333 0.1316667 0.1316667 0.1333333 0.1333333 0.1166667 0.1166667 0.1200000
预期输出
对于我的真实的问题,每个分区对应于单个物种到所有其他独特物种的距离,因此,如果物种X有两个DNA序列代表它,而总共有10个物种,那么物种X的分区应该包含20个距离,但是我不希望分区包含物种A的两个序列之间的距离。splt
将因此包含用于所有种类的10个分区(每个分区不必具有相同长度a
和b
的预期输出是0-1之间的数字,包括0和1。我认为这些数字在我的真实的示例中应该很小,但当我尝试运行代码时,它们却很大,我认为这是warning()
的结果。
我所做的
我一直在读SO,%in%
通常用于解决警告
In splt[[i]] == splt[[j]] :
longer object length is not a multiple of shorter object length
除了在我的情况下,我相信我会需要%notin% <- Negate(%in%)
。
然而,%notin%
在我的原始帖子中给出了错误
the condition has length > 1
问题
如何更改嵌套循环以删除警告?
1条答案
按热度按时间bgibtngc1#
我将通过“解释”你所说的部分内容,抛弃你的代码,看看我能想出什么来。如果没有别的,它可能会引发对话,解释我的解释中哪些是正确的(哪些是不正确的)。
从随机数据生成的
splt
开始,然后用更长的向量替换元素4和5,我们有:
你引用了像
which(splt[[i]] >= min(splt[[j]]))
这样的表达式,我把它解释为“splt[[i]]
高于splt[[j]]
中最大值的比率是多少。(例如)splt[[1]]
与这里的splt[[2]]
到splt[[5]]
中的所有,并且对于其它的也是如此,我们会得到一个正方形matrix
,对角线是splt[[i]]
-vs-splt[[i]]
(可能没什么意思)。一些快速的数学运算,让我们知道我们最终应该得到什么:
由于
[[1]]
中的1大于2的最大值2.29,我们期望0.5
在两者之间进行比较(对于>= max(.)
);类似地,没有[[1]]
低于0.15,因此我们期望在那里有0
。类似地,
[[5]]
在[[4]]
上:我们可以使用
outer
,但有时候会让人感到困惑,特别是在这种情况下,我们需要对传递给它的anon-func执行Vectorize
。我将把双for
循环前提修改为嵌套的sapply
调用。大于另一个的最大值
判读和子集验证:
1
与max of 2
的关系:将X1 M23 N1 X(第一列)与来自X1 M24 N1 X(第二行)的最大值进行比较,X1 M25 N1 X的值的一半更大,因此我们得到0.5(如所期望的)。5
与max of 4
的关系:将X1 M28 N1 X(第五列)与来自X1 M29 N1 X(第四行)的最大值进行比较,X1 M30 N1 X满足条件。小于另一个的最小值
相同的两对:
1
与min of 2
(第2行,第1列)是0
,符合预期5
与min of 4
(第4行,第5列)是0.2
,符合预期sum(..)
应该会产生与length(which(..))
相同的结果,但后者可能对丢失数据更稳健(例如,NA
值,c.f.,Difference between sum(), length(which()), and nrow() in R)。对于共享该弹性的sum(..)
,在上面的调用中,我们应该将na.rm=TRUE)
添加到sum(.)
和min(.)
中。