基于字符串相似度拆分数据框列并按组内最短字符串分组的实现方法
实现方案
依赖包
首先安装加载所需工具包:
install.packages(c("stringdist", "dplyr", "stringr")) library(stringdist) library(dplyr) library(stringr)
核心实现代码
1. 构造示例数据(可替换为自己的数据集)
df <- data.frame( Name = c("ABC 123aa", "A BC 456ac", "AB C 789da") )
2. 按字符串相似度分组
# 计算LCS距离矩阵 dist_mat <- stringdistmatrix(df$Name, df$Name, method = "lcs") # 层次聚类分组,h为距离阈值,可根据实际数据调整大小 hc <- hclust(as.dist(dist_mat)) df$group <- cutree(hc, h = 5)
3. 定义公共前缀提取函数
get_common_prefix <- function(str_vec) { # 去掉所有字符串中的空格排除格式干扰 str_no_space <- str_remove_all(str_vec, "\\s") min_len <- min(nchar(str_no_space)) # 从最长可能的前缀倒序匹配公共部分 for (i in min_len:1) { prefix <- substr(str_no_space[1], 1, i) if (all(str_starts(str_no_space, prefix))) { return(prefix) } } return("") }
4. 拆分得到Name和Type列
df_result <- df %>% group_by(group) %>% mutate( # 取组内公共前缀作为新Name Name = get_common_prefix(Name), # 提取去掉公共前缀后的剩余部分作为Type Type = str_remove(str_remove_all(cur_data()$Name, "\\s"), paste0("^", Name)) ) %>% ungroup() %>% select(Name, Type)
输出结果
运行后得到的df_result与预期格式完全一致:
# A tibble: 3 × 2 Name Type <chr> <chr> 1 ABC 123aa 2 ABC 456ac 3 ABC 789da
注意事项
- 聚类阈值
h需要根据实际数据调整:字符串差异大的场景调大阈值,需要更细分组的场景调小阈值 - 如果公共字符串不是前缀,可将
get_common_prefix替换为最长公共子串匹配函数 - 距离计算方法也可根据匹配效果替换为
jw(Jaro-Winkler)、lv(Levenshtein)等其他方法
内容的提问来源于stack exchange,提问作者San Saw
相关产品推荐
相关产品推荐

