如何高效处理字符串并与firstname、lastname数据框匹配?
问题描述
现有以下三个数据集:
字符串数据集strings
strings <- structure(list(string = c("Jennifer Rae Hancock Brown", "Lisa Smith Houston Blogger", "Tina Fay Las Cruces", "\t\nJamie Tucker Style Expert", "Jessica Wright Htx Satx", "Julie Green Lifestyle Blogger", "Mike S Thomas Football Player", "Tiny Fitness Houston Studio")), class = "data.frame", row.names = c(NA, -8L))
名字数据集firstname和lastname
firstname <- structure(list(firstnames = c("Jennifer", "Lisa", "Tina", "Jamie", "Jessica", "Julie", "Mike", "George")), class = "data.frame", row.names = c(NA, -8L)) lastname <- structure(list(lastnames = c("Hancock", "Smith", "Houston", "Fay", "Tucker", "Wright", "Green", "Thomas")), class = "data.frame", row.names = c(NA, -8L))
需要完成以下操作:
- 截取每个字符串的前三个单词,例如将
"Jennifer Rae Hancock Brown"处理为"Jennifer Rae Hancock","Lisa Smith Houston Blogger"处理为"Lisa Smith Houston";
- 截取每个字符串的前三个单词,例如将
- 检查处理后字符串的第一个单词是否存在于
firstname数据框中,匹配则生成firstname列存储匹配值,不匹配填"N/A";
- 检查处理后字符串的第一个单词是否存在于
- 检查处理后字符串的剩余单词是否存在于
lastname数据框中,存在多个匹配则拆分多行存储对应结果。
- 检查处理后字符串的剩余单词是否存在于
最终要得到如下格式的final数据框:
final <- structure(list(string = c("Jennifer Rae Hancock Brown", "Lisa Smith Houston Blogger", "Lisa Smith Houston Blogger", "Tina Fay Las Cruces", "\t\nJamie Tucker Style Expert", "Jessica Wright Htx Satx", "Julie Green Lifestyle Blogger", "Mike S Thomas Football Player", "Tiny George Fitness Houston Studio"), firstname = c("Jennifer", "Lisa", "Lisa", "Tina", "Jamie", "Jessica", "Julie", "Mike", "N/A"), lastname = c("Hancock", "Smith", "Houston", "Fay", "Tucker", "Wright", "Green", "Thomas", "N/A")), class = "data.frame", row.names = c(NA, -9L))
高效实现方法
推荐使用tidyverse工具集(dplyr+stringr+tidyr)完成,代码简洁且逻辑清晰:
步骤1:加载依赖包
library(tidyverse)
步骤2:预处理字符串,提取前三个单词并拆分
processed <- strings %>% # 去除字符串首尾空白(含制表符、换行符) mutate(clean_string = str_trim(string)) %>% # 提取前三个单词,兼容单词数不足3的情况 mutate(first_three_words = str_extract(clean_string, "^\\S+\\s+\\S+\\s+\\S+|^\\S+\\s+\\S+|^\\S+")) %>% # 拆分第一个单词和剩余所有单词 separate(first_three_words, into = c("first_word", "rest_words"), sep = "\\s+", extra = "merge", fill = "right") %>% # 将剩余单词拆分为单个单词的列表,方便后续展开多行 mutate(rest_words = str_split(rest_words, "\\s+"))
步骤3:匹配名字并展开多行
final_result <- processed %>% # 匹配名字:判断首词是否在firstname集合中 mutate(firstname = ifelse(first_word %in% firstname$firstnames, first_word, "N/A")) %>% # 将剩余单词列表展开为多行 unnest(rest_words, keep_empty = TRUE) %>% # 匹配姓氏:判断单词是否在lastname集合中,无匹配则填"N/A" mutate(lastname = ifelse(rest_words %in% lastname$lastnames, rest_words, "N/A")) %>% # 处理剩余单词为空的情况,填充"N/A" mutate(lastname = replace_na(lastname, "N/A")) %>% # 保留目标格式需要的列 select(string, firstname, lastname) %>% # 去重无效行 distinct()
验证结果
可以用以下代码检查结果是否与目标final一致:
all.equal(final_result, final)
代码说明
str_trim():清理字符串首尾的干扰空白字符,避免影响单词提取;str_extract():用正则精准匹配前三个单词,兼容单词数不足3的场景;separate()+str_split():拆分首词与剩余单词,将剩余单词转为列表格式,为后续多行展开做准备;unnest():快速将列表型数据展开为多行,实现多匹配结果的拆分;%in%:基于集合的快速匹配,效率远高于循环判断。
内容的提问来源于stack exchange,提问作者wizkids121
相关产品推荐
相关产品推荐

