R语言:去除数据框姓名列重复项(含全名与姓氏去重)
问题描述
我有一个包含姓名字符串的数据框:
df = data.frame("names" = c("George Orwell; Ayn Rand; Adam Smith", "George Orwell; Rand; Orwell")) df # names # 1 George Orwell; Ayn Rand; Adam Smith # 2 George Orwell; Rand; Orwell
我需要移除所有重复姓名,规则如下:
- 仅保留列表中的唯一姓名
- 当字符串中存在某姓氏对应的全名时,移除单独的姓氏;若没有对应全名,则保留该姓氏
期望得到的结果:
names 1 George Orwell; Ayn Rand; Adam Smith 2 George Orwell; Rand
目前我用以下代码只能处理完全重复的情况,无法解决姓氏与全名的冗余问题:
sapply(strsplit(df$names, ";\\s*"), function(z) paste(unique(z), collapse = "; ")) # [1] "George Orwell; Ayn Rand; Adam Smith" "George Orwell; Rand; Orwell"
解决方案
可以通过自定义函数实现姓氏与全名的匹配过滤,具体代码如下:
clean_names <- function(name_vec) { # 拆分每个姓名为若干部分,区分全名(多部分)和单姓氏 split_parts <- strsplit(name_vec, "\\s+") # 提取每个姓名的姓氏 last_names <- sapply(split_parts, function(x) x[length(x)]) # 筛选出所有全名(包含至少两个部分的姓名) full_name_list <- name_vec[sapply(split_parts, length) >= 2] # 提取全名对应的姓氏集合 full_last_names <- sapply(strsplit(full_name_list, "\\s+"), function(x) x[length(x)]) # 过滤规则:单姓氏且对应全名存在则移除,其余保留 keep_flag <- !((sapply(split_parts, length) == 1) & (last_names %in% full_last_names)) # 最后做一次完全去重,再合并为字符串 unique(name_vec[keep_flag]) } # 将函数应用到数据框的names列 df$cleaned_names <- sapply(strsplit(df$names, ";\\s*"), function(z) { paste(clean_names(z), collapse = "; ") }) # 查看处理后的结果 df$cleaned_names # [1] "George Orwell; Ayn Rand; Adam Smith" "George Orwell; Rand"
代码说明
- 拆分姓名:通过空格拆分每个姓名,判断是全名(多段)还是单姓氏
- 提取姓氏:从每个姓名中提取最后一段作为姓氏
- 匹配过滤:如果某个单姓氏对应的全名已经存在,则移除该单姓氏
- 去重合并:对过滤后的结果做完全去重,再合并为目标格式的字符串
内容的提问来源于stack exchange,提问作者user17661126
相关产品推荐
相关产品推荐

