如何提取姓名中的名、中间名与姓氏?并处理后缀问题
姓名拆分:提取名、中间名、姓氏并处理后缀干扰
问题背景
需要从姓名数据中提取名(First Name)、姓氏(Last Name),其余部分归类为中间名(Middle Names)。现有R拆分代码在实际数据集运行时,发现后缀(如jr、sr、I、II、III等)会干扰拆分逻辑,需在正则拆分前先去除这些后缀。
可复现示例数据
# 示例数据集(含带后缀的测试用例) Sample_Dataset <- structure(list( MemberName = c("David owino", "Prisca omanya", "Geraldine nyambura bitange", "Ruiz aguila de espinoza", "Hera nyabute oganche", "Joney boka", "John doe jr", "Robert smith III"), `Date of Birth` = structure(c(-235094400, 252806400, -641606400, 613180800, 697852800, 684115200, 1234567890, 987654321), tzone = "UTC", class = c("POSIXct", "POSIXt")), `PCP Name` = c("Ogero, Lamech, Md :1677742950", "Njeri, Lamech, Np :1677742951", "Ogero, Lamech, Md :1677742952", "Agero, Larisse, Md :1677742953", "Ogero, Lamech, Md :1677742954", "Denise, Lamech, Md :1677742955", "Doe, John, Jr :1677742956", "Smith, Robert, III :1677742957") ), row.names = c(NA, -8L), class = c("tbl_df", "tbl", "data.frame"))
现有尝试代码
初始拆分代码
# 初始拆分逻辑 String <- stringr::str_split(Sample_Dataset$MemberName, "[ ]", n = 2) Last_Name <- sapply(String, '[', -1) First_Name <- sapply(String, '[', 1) Sample_d2 <- data.frame(First_Name, Last_Name)
尝试提取中间名的代码(存在逻辑错误)
names.split <- strsplit(unlist(Sample_d2$Last_Name), " ") Middle_Names <- sapply(names.split$Last_Name, function(x) if(length(String$Last_Name) == 2) { Middle_Names <- sapply(String, '[', 1) } else if (length(String$Last_Name) == 3){ Middle_Names <- sapply(String, '[', 1:2) } ) Sample_d2 <- data.frame(First_Name,Middle_Names, Last_Name)
解决方案:先去后缀再拆分
核心思路
- 用正则匹配并移除常见姓名后缀(jr、sr、I~IV等,不区分大小写)
- 对清理后的姓名进行拆分:
- 第一个词为名
- 最后一个词为姓氏
- 中间所有词合并为中间名
完整实现代码
library(stringr) library(dplyr) # 1. 定义后缀正则:匹配末尾的jr/sr/I/II/III/IV,忽略大小写 suffix_pattern <- "\\s+(jr|sr|I{1,3}|IV)$" # 2. 清理姓名:移除后缀并统一首字母大写 Sample_Dataset <- Sample_Dataset %>% mutate(CleanedName = MemberName %>% str_to_lower() %>% str_remove_all(suffix_pattern) %>% str_to_title()) # 3. 拆分姓名组件 name_components <- str_split(Sample_Dataset$CleanedName, "\\s+") # 提取各字段 Sample_Dataset <- Sample_Dataset %>% mutate( First_Name = sapply(name_components, function(x) x[1]), Last_Name = sapply(name_components, function(x) x[length(x)]), Middle_Names = sapply(name_components, function(x) { if(length(x) <= 2) "" else paste(x[2:(length(x)-1)], collapse = " ") }) ) # 查看结果 Sample_Dataset %>% select(MemberName, CleanedName, First_Name, Middle_Names, Last_Name)
运行结果示例
| MemberName | CleanedName | First_Name | Middle_Names | Last_Name |
|---|---|---|---|---|
| David owino | David Owino | David | Owino | |
| Prisca omanya | Prisca Omanya | Prisca | Omanya | |
| Geraldine nyambura bitange | Geraldine Nyambura Bitange | Geraldine | Nyambura | Bitange |
| Ruiz aguila de espinoza | Ruiz Aguila De Espinoza | Ruiz | Aguila De | Espinoza |
| Hera nyabute oganche | Hera Nyabute Oganche | Hera | Nyabute | Oganche |
| Joney boka | Joney Boka | Joney | Boka | |
| John doe jr | John Doe | John | Doe | |
| Robert smith III | Robert Smith | Robert | Smith |
内容的提问来源于stack exchange,提问作者NewData_Nomad
相关产品推荐
相关产品推荐

