【问题标题】:separate different combinations of names to first and last using dplyr, tidyr, and regex使用 dplyr、tidyr 和 regex 将不同的名称组合分隔到第一个和最后一个
【发布时间】:2016-11-01 15:53:26
【问题描述】:

示例数据框:

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 和正则表达式来实现这一点,但我会采取任何解决方案。感谢您的帮助

【问题讨论】:

标签: r regex dplyr tidyr stringr


【解决方案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

【讨论】:

    【解决方案2】:

    我不确定这是否比 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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-28
      • 2022-01-13
      • 1970-01-01
      • 2018-07-27
      • 2023-03-13
      • 1970-01-01
      相关资源
      最近更新 更多