查找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")
我想匹配 ref 和 expr 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 中的正则表达式 - 查找字符之间的最小长度