Levenshtein实现能够处理大字符串和向量

时间:2016-04-26 11:33:46

标签: python r perl levenshtein-distance stringdist

R中有package名为stringdist,其中包含用于计算Levenshtein字符串距离的函数。我对这个包有两个问题:

第一它不适用于大字符串,例如:

set.seed(1)
a.str <- paste(sample(0:9, 100000, replace = T), collapse="")

set.seed(2)
b.str <- paste(sample(0:9, 100000, replace = T), collapse="")

stringdist(a.str, b.str, method = "lv")
# THE LAST COMMAND RESTARTS R SESSION

2nd 向量中的距离是根据向量元素的字符计算的,而不是按照整个向量计算的:

a.vec <- c(1, 2, 3, 4, 5, 666)
b.vec <- c(1, 2, 4, 3, 6, 777)
stringdist(a.vec, b.vec, method = "lv")
# [1] 0 0 1 1 1 3

我想得到最后一个命令4的结果:因为需要4个替换(相应位置上的4个向量元素不同)。在这种情况下,我可以获取非0的值并计算它们,例如:r <- stringdist(a.vec, b.vec, method = "lv"); length(r[r!=0])。但它不适用于以下示例:

a.vec <- c(1, 2, 3)
b.vec <- c(1, 2, 2, 3)
stringdist(a.vec, b.vec, method = "lv")
# [1] 0 0 1 1
# Warning message:
# In stringdist(a.vec, b.vec, method = "lv") :
#   longer object length is not a multiple of shorter object length

我想得到最后一个命令1的结果(在第一个向量的第一个位置插入2)。

PS 还有内置的实现,但它也不适用于大字符串(说实话我不知道它是如何使用向量的,因为我不理解它的输出):

adist(a.str,b.str, counts = T)
# Error in adist(a.str, b.str, counts = T) : 
#   'Calloc' could not allocate memory (1410265409 of 8 bytes)

是否有任何符合我要求的实现(最好是在python,perl或R中)?非常感谢你。

PPS 我有多个文件,其中每行包含1~500的数字(这就是为什么我需要将例如3​​47视为一个元素而不是由3,4,7组成的字符串,因为3 ,4,7是另一个单独的数字)。那些文件有~25万行。我想知道这些文件彼此之间有多相似。我想10k * 10k的尺寸是个问题。但是here被提到Levenshtein算法,它只使用2 * 10k大小(如果两个字符串都是10k长)。我想诀窍是它只计算结果并忘记计算结果如何,但这对我来说没问题。汉明距离对我来说是不够的,因为我需要考虑插入,删除,替换,在汉明这两个字符串1234567890 0123456789是完全不同的,但在Levenshtein中它们是相似的。

1 个答案:

答案 0 :(得分:1)

以下是内存问题的解决方案:

library(RecordLinkage)

set.seed(1)
a.str <- paste(sample(0:9, 100000, replace = T), collapse="")
set.seed(2)
b.str <- paste(sample(0:9, 100000, replace = T), collapse="")
levenshteinDist(a.str, b.str)
[1] 73969

仍然需要使用paste将向量转换为字符串,因为包不会自动承担。大多数用例都需要矢量化操作。

请参阅下文,了解如何将它们视为字符串:

a.vec <- c(1, 2, 3, 4, 5, 666)
b.vec <- c(1, 2, 4, 3, 6, 777)
levenshteinDist(paste(a.vec, collapse = ''), paste(b.vec, collapse = ''))
[1] 5