【问题标题】:Levenshtein implementation capable working with large strings and vectorsLevenshtein 实现能够处理大字符串和向量
【发布时间】:2016-08-20 05:05:33
【问题描述】:

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

1st 它不适用于大字符串,例如:

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

第二向量中的距离是按向量元素的字符而不是按整个向量计算的:

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 &lt;- 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 的数字(这就是为什么我需要将例如 347 视为一个元素而不是由 3、4、7 组成的字符串,因为 3 ,4,7 是另一个单独的数字)。这些文件有 ~ 250000 行。我想知道这些文件彼此之间有多相似。我想 10k*10k 大小是问题所在。但是here 提到了仅使用 2*10k 大小的 Levenshtein 算法(如果两个字符串都是 10k 长)。我想诀窍是它只计算结果而忘记了结果是如何计算的,但这对我来说没问题。汉明距离对我来说是不够的,因为我需要考虑插入、删除、替换,在汉明中这两个字符串 1234567890 0123456789 完全不同,但在 Levenshtein 中它们是相似的。

【问题讨论】:

  • 100000 * 100000 是 10GB。不确定你的目标是什么。为什么要在这么大的字符串上计算 stringdist
  • 例如,method=JWstringdist 中的相同两个字符串上会产生结果。算法不同,不需要平方的内存。
  • 至于您所采用的矢量化方法stringdist 的其他问题,这对于大多数用例来说是一件非常好的事情。如果你真的不希望它把这两个输入当作向量,你可以使用stringdist(paste(a.vec, collapse = ''), paste(b.vec, collapse = ''), method = "lv")
  • 这可能会有所帮助:stackoverflow.com/questions/4057513/…
  • @Gopala 我可以例如用零为所有元素添加前缀并获取例如007455 但问题是它会增加已经很大的字符串,所以我想避免这种情况并改用向量。

标签: python r perl levenshtein-distance stringdist


【解决方案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

【讨论】:

  • 谢谢,我投了赞成票,但我仍然需要向量。请问你是怎么找到包裹的?
  • 我以前用它来链接记录,现在忘记了。所以,重新加载并尝试。将编辑以添加矢量方面。希望能满足您的需求。
  • 并非在所有情况下都有效。在这里检查我的问题:cs.stackexchange.com/questions/56612/…
猜你喜欢
  • 2010-11-25
  • 1970-01-01
  • 2014-05-17
  • 2011-06-15
  • 2013-03-19
  • 2015-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多