查找字符串和长字符串向量之间的最小汉明距离(快速)

时间:2018-08-19 13:36:45

标签: r string performance vectorization hamming-distance

我需要计算输入字符串和大字符串数据集之间的汉明距离。 (数据集中的所有字符串都具有与输入字符串相同的长度。

例如,如果

input <- "YNYYEY"
dataset <- c("YNYYEE", "YNYYYY", "YNENEN", "YNYYEY")

inputdataset中每个字符串之间的汉明距离为1、1、3、0,因此最小值为0。我编写了一个函数来计算两个字符串之间的汉明距离:< / p>

HD <- function(str1, str2){

   str1 <- as.character(str1)
   str2 <- as.character(str2)

   length.str1 <- nchar(str1)
   length.str2 <- nchar(str2)

   string.temp1 <- c()
   for (i in 1:length.str1){
     string.temp1[i] = substr(str1, start=i, stop=i)
   }
   string.temp2 <- c()
   for (i in 1:length.str2){
     string.temp2[i] = substr(str2, start=i, stop=i)
   }
   return(sum(string.temp1 != string.temp2))
   }

但是数据集太大,因此我需要加快速度,您是否知道我可以快速完成?谢谢您的帮助。

2 个答案:

答案 0 :(得分:2)

您无法比O(n)更好地改进它,这意味着您必须查看所有数据集,并计算每个观测值的距离。

如果您sort基于给定点的所有观测值,则只能对数据集进行改进。在这种情况下,您可能更容易在数据集中找到一个字符串(距离结果为0)。这是您唯一可以做的改进。

答案 1 :(得分:2)

在R级别,您可以使用strsplitcbind!=colSumsmin。它们都是“矢量化的”。

a <- "YNYYEY"
b <- c("YNYYEE", "YNYYYY", "YNENEN", "YNYYEY")
A <- strsplit(a, split = "")[[1]]
#[1] "Y" "N" "Y" "Y" "E" "Y"
B <- do.call("cbind", strsplit(b, split = ""))
#     [,1] [,2] [,3] [,4]
#[1,] "Y"  "Y"  "Y"  "Y" 
#[2,] "N"  "N"  "N"  "N" 
#[3,] "Y"  "Y"  "E"  "Y" 
#[4,] "Y"  "Y"  "N"  "Y" 
#[5,] "E"  "Y"  "E"  "E" 
#[6,] "E"  "Y"  "N"  "Y" 
D <- colSums(A != B)
#[1] 1 1 3 0
min(D)
#[1] 0

This kind of "vectorization" creates many temporary matrices / vectors and uses plenty of RAM。但是希望这是值得的。

在C / C ++级别上,您可以做得更好(请参阅here的案例研究),但是我今天并不热衷于编写C / C ++代码。


我遇到了stringdist包(甚至还有一个标签)。函数stringdist依赖于用C语言编写的主力例程stringdist:::do_dist

library(stringdist)
d <- stringdist(a, b, method = "hamming")
#[1] 1 1 3 0
min(d)
#[1] 0
  

stringdist()的运行速度比colSum()慢十倍。

那真的很有趣。也许它的C代码或R代码正在做其他复杂的事情。