使用正则表达式提取名称和数字

时间:2018-07-04 01:22:11

标签: r regex stringr

我认为我在理解R中的正则表达式时可能会遇到一些问题。

我需要从样本向量中提取电话号码和姓名,并使用Stringer软件包功能创建一个具有相应列的名称和号码数据框。

以下是我的样本向量。

phones <- c("Ann 077-789663", "Johnathan 99656565",
            "Maria2 099-65-6569 office")

我提取这些代码的代码如下

numbers <- str_remove_all(phones, pattern = "[^0-9]")
numbers <- str_remove_all(numbers, pattern = "[a-zA-Z]")
numbers <- trimws(numbers)

names <- str_remove_all(phones, pattern = "[A-Za-z]+", simplify = T)

phones_data <- data.frame("Name" = names, "Phone" = numbers)

它不起作用,因为它将姓名中的数字与电话号码合并在一起。 (也不是最佳代码)

在解释完成此任务的最简单方法方面,我将提供一些帮助。

3 个答案:

答案 0 :(得分:1)

不是正则表达式专家,但是,使用stringr包,我们可以提取带有可选“-”的数字模式,然后用空字符串替换“-”以提取没有任何“-”的数字。对于名称,我们在字符串的开头提取第一个单词。

library(stringr)
data.frame(Name = str_extract(phones, "^[A-Za-z]+"), 
           Number = gsub("-","",str_extract(phones, "[0-9]+[-]?[0-9]+[-]?[0-9]+")))


#       Name    Number
#1       Ann 077789663
#2 Johnathan  99656565
#3     Maria 099656569

如果您想完全坚持使用stringr,我们可以使用str_replace_all代替gsub

data.frame(Name = str_extract(phones, "[A-Za-z]+"), 
Number=str_replace_all(str_extract(phones, "[0-9]+[-]?[0-9]+[-]?[0-9]+"), "-",""))

#       Name    Number
#1       Ann 077789663
#2 Johnathan  99656565
#3     Maria 099656569

答案 1 :(得分:1)

我认为Ronak的答案对于名字部分是有好处的,我真的没有一个很好的选择。

对于数字,我将使用“数字和连字符,两端带有单词边界”,即

numbers = str_extract(phones, "\\b[-0-9]+\\b") %>%
    str_remove_all("-")
# Can also specify that you need at least 5 numbers/hyphens 
# in a row to match
numbers2 = str_extract(phones, "\\b[-0-9]{5,}\\b") %>%
    str_remove_all("-")

这样,您就不会因为数字中出现的连字符数量而被锁定为固定格式(我建议的正则表达式允许使用任何数字)。

答案 2 :(得分:0)

如果您(像我一样)更喜欢使用base-R并希望使正则表达式尽可能简单,则可以执行以下操作:

phone_split <- lapply(
  strsplit(phones, " "), 
  function(x) {
    name_part <- grepl("[^-0-9]", x)
    c(
      name = paste(x[name_part], collapse = " "),
      phone = x[!name_part]
    )
  }
)
phone_split
[[1]]
        name        phone 
       "Ann" "077-789663" 

[[2]]
       name       phone 
"Johnathan"  "99656565" 

[[3]]
           name           phone 
"Maria2 office"   "099-65-6569" 

do.call(rbind, phone_split)

     name            phone        
[1,] "Ann"           "077-789663" 
[2,] "Johnathan"     "99656565"   
[3,] "Maria2 office" "099-65-6569"