有什么方法可以评估这两个名称之间的相似性吗?数据如下:
ABC ABCD
CBD CBD
ABC DEF
结果可能类似
ABC ABCD (3/4=) 75%
CBD CBD (3/3=) 100%
ABC DEF (0/6=) 0%
此外,字符的顺序与无关
使用intersect
的length
除以最小nchar
的max
,按行计算apply
。我们可以选择处理重复。
# V1 V2
# 1 ABC ABCD
# 2 CBD CBD
# 3 ABC DEF
# 4 ABCCC ABCC
# 5 ABCCC ABCCC
# 6 ABCCC ABCD
f <- function(x, dupes=FALSE) {
if (dupes) {
x <- sapply(x, function(x) Reduce(paste0, unique(el(strsplit(x, "")))))
}
i <- length(do.call(intersect, unname(mapply(strsplit, x, ""))))
m <- max(sapply(x, nchar))
i/m
}
apply(d, 1, f)
# [1] 0.75 1.00 0.00 0.60 0.60 0.60
apply(d, 1, f, dupes=TRUE)
# [1] 0.75 1.00 0.00 1.00 1.00 0.75
数据:
d <- structure(list(V1 = c("ABC", "CBD", "ABC", "ABCCC", "ABCCC",
"ABCCC"), V2 = c("ABCD", "CBD", "DEF", "ABCC", "ABCCC", "ABCD"
)), class = "data.frame", row.names = c(NA, -6L))
如果我理解正确,这段代码将提供预期的输出。
fun_str_sml <- function(str1, str2){
letters_list <- c(str1, str2) %>% map(~ str_split(., "")[[1]]) %>% reduce(c)
return(letters_list %>% duplicated() %>% sum() / letters_list %>% unique() %>% length())
}
fun_str_sml("ABC", "ABCD") # => 0.75
fun_str_sml("ABC", "CDEF") # => 0.1666667 (1/6)
对mapply
:使用集合运算
mapply(function(x, y) length(intersect(x, y))/length(union(x, y)),
strsplit(df$V1, ''), strsplit(df$V2, '')) * 100
#[1] 75 100 0