R:当电子邮件有多个域名后缀时,如何将电子邮件拆分成多个部分?

R: How do I split an email into parts when the emails have multiple domain endings?

我正在尝试分析存储在数据框 (data$Email.Address) 中的电子邮件列表,我想首先将电子邮件分成几部分,这样 example1@gmail.com、example2@outlook.org 和 example3@comcast.net 就这样结束了:

   email                 firstpart secondpart thirdpart

1  example1@gmail.com    example1  gmail      com
2  example2@outlook.org  example2  outlook    org
3  example3@comcast.net  example3  comcast    net

然而,使用我当前的代码,我无法匹配所有字符串 — 因为有些 包括像 (some-url.com) 或 (us.army.mil) 这样的域。这意味着 example4@us.army.mil 显示为:

    email                  firstpart secondpart thirdpart
4   example4@us.army.mil   example4  us         army

我的目标是阅读“some-url”或“us.army”作为第二部分,“com”和“mil”作为第三部分,这样就显示出来了像这样:

    email                  firstpart secondpart thirdpart
4   example4@us.army.mil   example4  us.army    mil

这是我的代码:

library(tidyverse)
library(dplyr)
library(stringr)
library(rebus)

email_pattern <- capture(one_or_more(WRD)) %R%
  "@" %R% capture(one_or_more(x = WRD)) %R% 
  DOT %R% capture(one_or_more(WRD)) 

#Split the emails into parts based on the pattern
email_parts <- str_match(data$Email.Address, pattern = email_pattern)

如何更改代码以便可以读取所有域?谢谢!

使用 stringidata.tabletstrsplit():

library(stringi)
library(data.table)
df[paste0("part", 1:3)] <- 
  tstrsplit(stri_replace_last(df$email, fixed = ".", "@"), split = "@")

                 email    part1   part2 part3
1   example1@gmail.com example1   gmail   com
2 example2@outlook.org example2 outlook   org
3 example3@comcast.net example3 comcast   net
4 example4@us.army.mil example4 us.army   mil

可复现数据(下次请自行提供):

df <- data.frame(
  email = c(
    "example1@gmail.com", "example2@outlook.org", "example3@comcast.net", "example4@us.army.mil"
  )
)

您还可以将正则表达式捕获组与 tidyr::extract() 结合使用。

library(tidyr)

df %>%
  extract(email, c("firstpart", "secondpart", "thirdpart"), 
          "([A-Za-z0-9_.]+)@([a-z.]+)\.([a-z]+)$", remove = FALSE)

                 email firstpart secondpart thirdpart
1   example1@gmail.com  example1      gmail       com
2 example2@outlook.org  example2    outlook       org
3 example3@comcast.net  example3    comcast       net
4 example4@us.army.mil  example4    us.army       mil

这是分组的细目 -- 用括号表示。

第一个 ([A-Za-z0-9_.]+) 连续捕获包含 @ 之前的那些字符的所有内容。在这里您需要明确说明可以包含哪些字符。您也可以在这里使用 (.+?)([[:print:]]?),但我更喜欢明确。

第二个 ([a-z.]+) 捕获电子邮件地址中最后一个句点之前的所有小写字母和句点(由括号中的 \. 表示)。

最后一个 ([a-z]+)$ 捕获所有小写字母,直到字符串结束。

这是使用 sindri_baldur 的示例数据的基础 R 解决方案:

df <- data.frame(email = c("example1@gmail.com", "example2@outlook.org", "example3@comcast.net", "example4@us.army.mil"))
df$firstpart <- sapply(strsplit(df$email, "@"), function (x) {
  x[1]
})
df$secondpart <- strsplit(sapply(strsplit(df$email, "@"), function (x) {
  x[2]
}), "[.][[:alpha:]]+$")
df$thirdpart <- sapply(seq_len(nrow(df)), function (x) {
  gsub(paste0(df$firstpart[x], "@", df$secondpart[x], "."), "", df$email[x])
})
df
#                  email firstpart secondpart thirdpart
# 1   example1@gmail.com  example1      gmail       com
# 2 example2@outlook.org  example2    outlook       org
# 3 example3@comcast.net  example3    comcast       net
# 4 example4@us.army.mil  example4    us.army       mil

我看到你找到了一些有效的答案,但我想我会把它带回你原来的 dplyrtidyr 工作流程。我认为您缺少的关键正则表达式是 "\.(?=[^.]+$)"(抓住最后一段之后的内容)。

由于我迟到了,我在您的播放数据框中添加了第五个异想天开的条目...

library(dplyr)
library(tidyr)

df <- data.frame(
   email = c(
      "example1@gmail.com", 
      "example2@outlook.org", 
      "example3@comcast.net", 
      "example4@us.army.mil",
      "example5@us.paratrooper.fort-benning.army.mil"
   )
)

df %>% 
   separate(email, "@", into = c("userid", "domain")) %>%
   separate(
      col = domain,
      into = c("secondpart", "thirdpart"),
      sep = "\.(?=[^.]+$)")
#>     userid                       secondpart thirdpart
#> 1 example1                            gmail       com
#> 2 example2                          outlook       org
#> 3 example3                          comcast       net
#> 4 example4                          us.army       mil
#> 5 example5 us.paratrooper.fort-benning.army       mil