在R语言中拆分数据框列:提取姓名、姓氏与出生日期
解决办法:利用正则精准拆分三部分
你的问题出在之前的处理只拆分了名字和「姓氏+生日」的组合,没把末尾的8位生日数字单独拆分出来。我们可以利用固定格式的生日(8位数字在末尾)和名字/姓氏的大小写规则来精准拆分。
方法一:分步拆分(先拆生日,再拆姓名)
先把末尾8位数字提取为Birthdate,剩下的部分再拆分为Name和Lastname:
library(dplyr) library(tidyr) # 构造示例数据框 df <- data.frame(User = c("JohnLenon03041965", "RogerFederer12021954", "RickLandsman01041975")) # 第一步:拆分出Birthdate和姓名组合 df <- df %>% mutate( Birthdate = sub(".*(\\d{8})$", "\\1", User), # 提取末尾8位数字 NameLast = sub("(\\d{8})$", "", User) # 去掉末尾8位,得到姓名组合 ) # 第二步:拆分姓名组合为Name和Lastname df <- df %>% separate(NameLast, into = c("Name", "Lastname"), sep = "(?=[A-Z])") # 在大写字母前拆分 # 整理列顺序并去掉临时列 df <- df %>% select(Name, Lastname, Birthdate)
运行后得到的结果就是你想要的:
Name Lastname Birthdate 1 John Lenon 03041965 2 Roger Federer 12021954 3 Rick Landsman 01041975
方法二:一次性拆分(用正则匹配三部分)
如果你想一步到位,可以用separate配合更精准的正则表达式,直接把User列拆成三列:
df %>% separate(User, into = c("Name", "Lastname", "Birthdate"), sep = "(?<=[a-z])(?=[A-Z])|(?<=[A-Za-z])(?=\\d{8})")
这里的正则表达式解释:
(?<=[a-z])(?=[A-Z]):匹配小写字母后面、大写字母前面的位置(用来拆分名字和姓氏,比如John和Lenon之间)(?<=[A-Za-z])(?=\\d{8}):匹配字母后面、8位数字前面的位置(用来拆分姓氏和生日,比如Lenon和03041965之间)
为什么之前的代码没成功?
你之前的gsub('([[:upper:]])', ' \\1', df$User)会给所有大写字母前加空格,包括开头的J/R/R,导致字符串开头多了空格,而且生日部分是数字,没有大写字母,所以不会被拆分,最后separate只能把名字和「姓氏+生日」分开,没法拆分生日。
内容的提问来源于stack exchange,提问作者Jigar Mehta
相关产品推荐
相关产品推荐

