使用mapply函数处理两个向量的问题。

3

我有一个R函数,用于计算两个向量的汉明距离:

Hamming = function(x,y){
get_dist = sum(x != y, na.rm=TRUE)
return(get_dist)
}

我希望将以下操作应用于两个矩阵M1,M2的每一行,而不使用for循环。目前我所拥有的代码使用了非常耗时的循环(其中L是M1和M2中行的数量):

xdiff = c()
for(i in 1:L){
    xdiff = c(xdiff, Hamming(M1[i,],M2[i,]))
}

我认为这可以通过执行以下操作来完成

mapply(Hamming, t(M1), t(M2))

(由于mapply是按列操作的,因此需要进行转置),但是这并不能为每行生成一个长度为L的汉明距离向量,所以也许我对mapply在做什么有误解。
是否有一种简单的mapply应用或R apply系列中的其他方法可以实现这个功能?

R 中,矩阵是一个向量。如果您将矩阵的行作为两个列表中的元素,则可以使用此方法。 - Ameya
我认为这可能是问题所在。问题是否由于M1、M2是数据框而不是矩阵数据类引起的?对于mapply来说,这是否很重要? - Max
一个 m-by-n 数据框被存储为长度为 n 的向量列表,每个向量的长度为 m。它会像任何其他长度为 n 的列表一样被 mapply 处理。这里 mapply 如何处理数据框是无关紧要的,因为 m-by-n 数据框的转置是一个 n-by-m 矩阵,而不是一个 n-by-m 数据框。例如,尝试运行 is.matrix(t(data.frame(a=1:2, b=1:2))) - Mikael Jagan
谢谢 - 我原以为一个 m x n 的矩阵会被存储为一个长度为 m 的向量,其元素是长度为 n 的向量。 - Max
1个回答

3
如果M1M2的维度相同,则可以简单地执行以下操作:
rowSums(M1 != M2, na.rm = TRUE)

您尝试使用 mapply 失败了,因为 m-by-n 矩阵存储为长度为 m*n 的向量,并且 mapply 将其作为向量处理。要使用 mapply 完成此操作,您需要将每个矩阵拆分为一系列行向量的列表:

mapply(Hamming, asplit(M1, 1L), asplit(M2, 1L))

vapply更好:

vapply(seq_len(nrow(M1)), function(i) Hamming(M1[i, ], M2[i, ]), 0L)

无论如何,只需使用rowSums


在上面的例子中,使用vapply而不是mapply有什么优势? rowSums替代方案对于这个特定的例子效果很好,但我编写了汉明距离示例,以便提出如何在两个矩阵中为向量使用apply的更广泛问题,因此mapply / vapply是最佳的通用解决方案。 - Max
mapply 调用有更多的开销,原因如下:(1) mapply 需要预先分配所有行向量的内存,并在整个调用期间使用,而 vapply 一次只使用一个行向量。(2) mapply 构造一个包含所有结果的中间列表,然后将它们解压成数组,而 vapply 在生成结果时将其复制到预分配的数组中。(3) 每个 asplit 调用都涉及一个 R 级别的 for 循环,这非常慢。 - Mikael Jagan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接