【问题标题】:Calculating Hamming distance for two vectors in R?计算R中两个向量的汉明距离?
【发布时间】:2012-01-25 02:32:52
【问题描述】:

我正在尝试计算 R 中两个向量之间的汉明距离。我目前正在尝试使用“e1071”包和 hamming.distance 函数,如下所示:

library(e1071)
H <- hamming.distance(X) 

其中 X 是具有 2 行和(在我的特定数据中)667 列的 data.frame,每个观察值都是 0 或 1。

最初我得到了错误:

Error: evaluation nested too deeply: infinite recursion / options(expressions=)?

经过一些研究,似乎有一种修复方法可能是增加 R 中的基本选项。我通过 options(expressions=5000) 进行了此操作,然后尝试使用不同的值代替 5000。但这只会产生错误:

Error: C stack usage is too close to the limit

我不是一个程序员,这个最新错误的修复似乎与包 e1071 中的某些内容有关,可能没有正确调用(或在正确的时间)。

关于我做错了什么有什么想法吗?我最终想要大量向量之间的汉明距离,这只是一个起点。如果这与内存分配有关,关于如何处理它的任何建议?

【问题讨论】:

  • 这实际上不是内存问题,而是堆栈问题:该函数是递归的,它调用自身的次数与列数一样多。您可能想检查是否有其他非递归实现(例如,通过键入library(sos); ???hamming),或实现您自己的。此外,我无法重现该问题(expressions 对我来说已经是 5000):有关您的平台的信息(例如,sessionInfo())可能会有所帮助。

标签: r


【解决方案1】:

我不知道 hamming.distance 在内部是如何工作的,但是计算 2 个向量的距离的简单方法就是

sum(x1 != x2)

或者,在这种情况下,

sum(X[1,] != X[2,])

如果向量的总数不是太大(比如几千个),您可以在嵌套循环中实现:

n <- nrow(X)
m <- matrix(nrow=n, ncol=n)
for(i in seq_len(n - 1))
    for(j in seq(i, n))
        m[j, i] <- m[i, j] <- sum(X[i,] != X[j,])

警告:未经测试。

【讨论】:

  • 太棒了!你们是一个巨大的帮助。这太棒了。
  • 小心 NA 测试。
【解决方案2】:

关于使用 HAMMING.DISTANCE 与包 e1071 的警告!

此包的实现强制将对象与带有 as.logical 的布尔值进行比较。这意味着 0 的值将为 FALSE,任何非零值都将为 TRUE。这意味着对于序列: 0 1 2 与 0 1 1 相比,汉明距离将被报告为 0 而不是正确的值 1——这个包将把 1 和 2 视为相等,因为 as.logical(1) == as.logical(2)。

这是错误的(在我看来)实现:

    > library("e1071", lib.loc="C:/Program Files/R/R-2.15.3/library")
    Loading required package: class
    > hamming.distance
    function (x, y) 
    {
        z <- NULL
        if (is.vector(x) && is.vector(y)) {
            z <- sum(as.logical(x) != as.logical(y))
        }
        else {
            z <- matrix(0, nrow = nrow(x), ncol = nrow(x))
            for (k in 1:(nrow(x) - 1)) {
                for (l in (k + 1):nrow(x)) {
                    z[k, l] <- hamming.distance(x[k, ], x[l, ])
                    z[l, k] <- z[k, l]
                }
            }
            dimnames(z) <- list(dimnames(x)[[1]], dimnames(x)[[1]])
        }
        z
    }
    <environment: namespace:e1071>

我的建议:不要使用。如上所述,汉明距离很容易实现。

【讨论】:

  • 感谢您对此的说明。我最终只是使用 Hong Ooi 提到的非常简单的方法来计算它。但总的来说,这是件好事。
  • 我继续向软件包维护者发送了一封关于此问题的电子邮件。
【解决方案3】:

hamming.distance 采用 两个 向量或矩阵,但不是数据框,所以你想要的可能是

m = as.matrix(X)
hamming.distance(m[1,], m[2,])

hamming.distance(as.matrix(X))

但正如所指出的,这在您的特定情况下与

sum(m[1,] != m[2,])

(一般来说,如果您拥有的不是异构结构,则避免使用data.frames,因为它们比矩阵慢得多)

【讨论】:

    【解决方案4】:

    作为对上述所有内容的补充:虽然汉明距离作为普通嵌套循环实现起来很简单,但就执行时间而言,对于较大的矩阵,事情可能很快就会失控。在 R 中,使用矩阵乘法来计算大型矩阵的所有列之间的汉明距离要高效得多。与 R 级嵌套循环相比,这非常快。一个示例实现可以在here 找到。

    【讨论】:

      【解决方案5】:
      sum(xor(x[1,],x[2,]))
      

      我不知道 'xor' 与 '!=' 的相对效率

      【讨论】:

      • xor 实现为 function (x, y) { (x | y) &amp; !(x &amp; y) }!= 是一个原始函数。我怀疑!= 效率更高。
      【解决方案6】:

      只是添加到 @HongOoi 我想指出在 R 中 !=== 当缺少其中一个值时返回 NA,因此它可能会产生误导性结果

      > c(1, NA) == 1:2
      [1] TRUE   NA
      

      但是%in% 输出FALSE 用于1 %in% NA 比较。因此,如果在比较向量时要将缺失值计为“不同”,则必须使用 sum(!((x != y) %in% FALSE)) 代码:

      > x <- c(1, 8, 5, NA, 5)
      > y <- 1:5
      > sum(!((x != y) %in% FALSE))
      [1] 3
      

      还请注意,xy 向量可能具有不同的长度,这会导致较短向量中的值缺失 - 您可以做两件事:截断较长的向量或声明在较短的向量是“不同的”。这可以用熟悉的 R 参数转换成独立函数:

      hamming <- function(x, y, na.rm = TRUE) {
        size <- 1:max(length(x) & length(y))
        x <- x[size]
        y <- y[size]
        if (na.rm) {
          del <- is.na(x) & is.na(y)
          x <- x[del]
          y <- y[del]
        }
        sum(!((x != y) %in% FALSE))
      }
      

      此功能使您可以选择是否要将缺失值计为“不同”(na.rm = FALSE)或忽略它们。对于na.rm = TRUE,如果向量的长度不同,则较长的向量会被截断。

      【讨论】:

        猜你喜欢
        • 2019-04-23
        • 1970-01-01
        • 2014-04-24
        • 2020-12-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-25
        • 1970-01-01
        相关资源
        最近更新 更多