示例数据框:
name <- c("Smith John Michael","Smith, John Michael","Smith John, Michael","Smith-John Michael","Smith-John, Michael")
df <- data.frame(name)
df
name
1 Smith John Michael
2 Smith, John Michael
3 Smith John, Michael
4 Smith-John Michael
5 Smith-John, Michael
我需要达到以下所需的输出:
name first.name last.name
1 Smith John Michael John Smith
2 Smith, John Michael John Smith
3 Smith John, Michael Michael Smith John
4 Smith-John Michael Michael Smith-John
5 Smith-John, Michael Michael Smith-John
规则是:如果字符串中有逗号,则之前的任何内容都是姓氏。逗号后面的第一个单词是名字。如果字符串中没有逗号,则第一个单词是姓氏,第二个单词是姓氏。带连字符的单词是一个单词。我宁愿用dplyr和regex来实现这一点,但我会采取任何解决方案。谢谢你的帮助
答案 0 :(得分:1)
根据strsplit
中是否有逗号,","
或" "
之间的name
切换,您可以实现所需的结果。在这里,我们定义了两个函数来使表示更清晰。您也可以在函数中内联代码。
get.last.name <- function(name) {
lapply(ifelse(grepl(",",name),strsplit(name,","),strsplit(name," ")),`[[`,1)
}
strsplit
的结果是一个列表。 lapply(...,'[[',1)
遍历此列表并从每个列表元素中提取第一个元素,这是姓氏。
get.first.name <- function(name) {
d <- lapply(ifelse(grepl(",",name),strsplit(name,","),strsplit(name," ")),`[[`,2)
lapply(strsplit(gsub("^ ","",d), " "),`[[`,1)
}
此函数类似,只是我们从strsplit
返回的每个列表元素中提取第二个元素,其中包含第一个名称。然后,我们使用gsub
删除任何起始空格,然后我们再次使用" "
拆分,以从strsplit
作为名字返回的每个列表元素中提取第一个元素。
将所有内容与dplyr
:
library(dplyr)
res <- df %>% mutate(first.name=get.first.name(name),
last.name=get.last.name(name))
结果如预期:
print(res)
## name first.name last.name
## 1 Smith John Michael John Smith
## 2 Smith, John Michael John Smith
## 3 Smith John, Michael Michael Smith John
## 4 Smith-John Michael Michael Smith-John
## 5 Smith-John, Michael Michael Smith-John
数据:强>
df <- structure(list(name = c("Smith John Michael", "Smith, John Michael",
"Smith John, Michael", "Smith-John Michael", "Smith-John, Michael"
)), .Names = "name", row.names = c(NA, -5L), class = "data.frame")
## name
##1 Smith John Michael
##2 Smith, John Michael
##3 Smith John, Michael
##4 Smith-John Michael
##5 Smith-John, Michael
答案 1 :(得分:0)
我不确定这是否比aichao的答案更好,但无论如何我都试了一下。我给出了正确的输出。
df1 <- df %>%
filter(grepl(",",name)) %>%
separate(name, c("last.name","first.middle.name"), sep = "\\,", remove=F) %>%
mutate(first.middle.name = trimws(first.middle.name)) %>%
separate(first.middle.name, c("first.name","middle.name"), sep="\\ ",remove=T) %>%
select(-middle.name)
df2 <- df %>%
filter(!grepl(",",name)) %>%
separate(name, c("last.name","first.name"), sep = "\\ ", remove=F)
df<-rbind(df1,df2)