查找R中字符串组之间的距离

Posted

技术标签:

【中文标题】查找R中字符串组之间的距离【英文标题】:Find the distance between groups of string in R 【发布时间】:2022-01-19 21:12:56 【问题描述】:

我有一个非常大的数据集,看起来像这样。

我有两种类型的数据框

    我的参考数据.frame
ref=c("cake","brownies")

和我的实验数据.frame

expr=c("cak","cakee","cake", "rownies","browwnies")

我想匹配 refexpr data.frames 并找到它们之间的列文斯坦距离。输出可能如下所示...

ref   expr      distance 
cake  cak         1
cake  cakee       1
cake  cake        0
cake  rownies    ...

在我测量了他们的列文斯坦距离后,我想将距离小于 3 的任何字符串聚类到一个聚类中,并且我的数据可能看起来像

ref        expr      distance  cluster
cake       cak         1         1
cake       cakee       1         1
cake       cake        0         1
brownies   rownies     1         2 
brownies   browwnies   1         2

任何关于如何继续前进的帮助或建议都非常感谢。目前我正在尝试很多 的 R 包来查找 data.frame 之间的距离,例如

library("DescTools")

但它们似乎效果不佳。

【问题讨论】:

谷歌搜索“字符串”和“距离”发现了一个恰当命名的 stringdist 函数,它巧合地计算了 Levenshtein 距离。我会从那开始。至于将它们组合在一起,可能就像用 distance 的 bin 进行分组一样简单,不确定。 谢谢埃文斯。是的,我在这个包和 amatch 函数上做了很多工作,但还没有运气。感谢您抽出宝贵时间观看 您希望每个参考词都有一个集群吗?查看距离超出您正在谈论的范围的示例(即距离> = 3)会有所帮助 你能包括你为获得距离所做的事情吗?我支持 stringdist 的推荐,我已经将它用于类似的项目 仅供参考 @r2evans 和我都删除了 tidyverse 标签,因为即使您可能想要使用其中一些包(它们都不是问题),标签有非常具体的说明它的用途:“如果您的问题与 tidyverse 的一个或两个组件有关,例如 dplyr 或 ggplot2,请不要使用。使用 那些 标签,并使用r 进行标签以获得更好的响应。 ...除非您的问题是关于整个 tidyverse 包、它的安装或它与您的系统的集成,否则请为您实际使用的包使用标签。” 【参考方案1】:

我有两种方法,一种是受严格监督且更手动的方法,另一种是监督较少的方法。包stringdist 有一堆不同的距离指标,其中"lv" 是Levenshtein。我添加了一个额外的观察“磅蛋糕”来测试一个离参考词太远的词。

选项 1

获取每个实验字符串与其中一个参考字符串之间的距离矩阵。如果您有 2 个相似的参考字符串,或者如果一个实验词同样接近 2 个参考,这可能会出现问题,但它适用于这种简单的情况。然后将矩阵重塑为数据框,并沿参考词计数以获得簇数。过滤距离小于阈值的情况。

library(dplyr)
library(stringdist)

max_dist <- 3

ref <- c("cake", "brownies")
expr <- c("cak", "cakee", "cake", "poundcake", "rownies","browwnies")

mtx <- stringdistmatrix(ref, expr, method = "lv", useNames = "strings")

mtx
#>          cak cakee cake poundcake rownies browwnies
#> cake       1     1    0         5       6         8
#> brownies   8     7    7         8       1         1

df1 <- as.data.frame(mtx) %>%
  tibble::rownames_to_column("ref") %>%
  tidyr::pivot_longer(-ref, names_to = "expr", values_to = "dist") %>%
  mutate(clust = as.numeric(forcats::as_factor(ref))) # could also use data.table::rleid

df1 %>%
  filter(dist <= max_dist)
#> # A tibble: 5 × 4
#>   ref      expr       dist clust
#>   <chr>    <chr>     <dbl> <dbl>
#> 1 cake     cak           1     1
#> 2 cake     cakee         1     1
#> 3 cake     cake          0     1
#> 4 brownies rownies       1     2
#> 5 brownies browwnies     1     2

选项 2

这可能适用于更复杂的情况。我用它来纠正人名的拼写,在那里我有一组不完整的正确标签可供使用。将所有单词组合成 1 个向量,得到一个距离矩阵(这次它将是正方形),然后使用阈值作为高度从层次聚类创建聚类以切割树。然后,您可以匹配每个单词的引用以获取集群的标签。

这里的缺点是您有一些行用于非实验性的参考词 - 请注意,例如“brownies”在实验性字符串中从未正确拼写,但现在您有了观察结果。

all_words <- c(ref, expr)
hc <- hclust(stringdistmatrix(all_words, method = "lv", useNames = "strings"))

df2 <- data.frame(word = c(ref, expr), 
                  clust = cutree(hc, h = max_dist)) %>%
  mutate(r = ref[clust])

df2 %>%
  filter(!is.na(r))
#>        word clust        r
#> 1      cake     1     cake
#> 2  brownies     2 brownies
#> 3       cak     1     cake
#> 4     cakee     1     cake
#> 5      cake     1     cake
#> 6   rownies     2 brownies
#> 7 browwnies     2 brownies

【讨论】:

以上是关于查找R中字符串组之间的距离的主要内容,如果未能解决你的问题,请参考以下文章

查找项目对之间的全局最小距离的算法

Pandas DataFrame 中的正则表达式 - 查找字符之间的最小长度

R中最长的公共子字符串在两个字符串之间找到不连续的匹配

ORACLE:如何使用 regexp_like 查找两个字符之间带有单引号的字符串?

使用python中的内置函数查找3d距离

查找用户是不是在给定坐标的给定距离内