我想提取特定列中的某些字符串并替换NA。 对于下面的data.frame,当电子邮件信息为NA时,我想将字符串提取到另一列中。 字符串始终在“主题”列中的“ developer_id =”和“&app_id”之间。
|Email | Subject | |a@site.com | developer_id=a@site.com&app_id=a&appname=a | |NA | developer_id=b@site.com&app_id=b&appname=b | |c@site.com | NA | |NA | developer_id=d@site.com&app_id=d&appname=d |
我期望的结果如下。
|Email | Subject | |a@site.com | developer_id=a@site.com&app_id=a&appname=a | |b@site.com | developer_id=b@site.com&app_id=b&appname=b | |c@site.com | NA | |d@site.com | developer_id=d@site.com&app_id=d&appname=d |
答案 0 :(得分:0)
使用base R
的一个选项是提取第二列的子字符串,该子字符串与第一列中的NA
元素相对应,并用提取的值更新第一列NA
元素。 / p>
i1 <- is.na(df1$Email) # create a logical index
df1$Email[i1] <- regmatches(df1$Subject[i1],
regexpr("[a-z]+@.*\\.com", df1$Subject[i1]))
df1
# Email Subject
#1 a@site.com developer_id=a@site.com&app_id=a&appname=a
#2 b@site.com developer_id=b@site.com&app_id=b&appname=b
#3 c@site.com <NA>
#4 d@site.com developer_id=d@site.com&app_id=d&appname=d
或使用tidyverse
library(tidyverse)
df1 %>%
mutate(Email = case_when(is.na(Email) ~ str_extract(Subject, "[a-z]+@.*\\.com"),
TRUE ~ Email))
此外,正如OP中提到的将单独的字符串用作标识符一样,我们可以对这些字符串使用正则表达式环视,即提取出developer_id=
之后且&app_id
之前的所有字符
df1 %>%
mutate(Email = case_when(is.na(Email) ~
str_extract(Subject, "(?<=developer_id\\=).*(?=&app_id)"),
TRUE ~ Email))
df1 <- structure(list(Email = c("a@site.com", NA, "c@site.com", NA),
Subject = c("developer_id=a@site.com&app_id=a&appname=a",
"developer_id=b@site.com&app_id=b&appname=b", NA,
"developer_id=d@site.com&app_id=d&appname=d"
)), class = "data.frame", row.names = c(NA, -4L))
答案 1 :(得分:0)
根据您的请求,
Subject == NA
时,Email = Email
Subject != NA
时,提取字符串
developer_id=
之间&app_id
此提取可以通过函数stringr::str_extract(x, pattern)
使用正则表达式pattern = "(?<=developer_id=).*(?=&app_id)"
。
第一部分(?<=developer_id=)
将找到字符后跟 developer_id=
。 .*
表示此模式之后的任何字符。之后,(?=&app_id)
将匹配后跟&app_id
的字符。
换句话说,我们可以在developer_id=
和&app_id
之间找到所需的部分。
使用dplyr::mutate
和ifelse()
,您可以轻松地转换给定的列。
library(tidyverse) # dplyr, stringr
mydf %>% # your data
mutate(Email = ifelse(
is.na(Subject),
Email,
str_extract(Subject, pattern = "(?<=developer_id=).*(?=&app_id)")
))
#> # A tibble: 4 x 2
#> Email Subject
#> <chr> <chr>
#> 1 a@site.com developer_id=a@site.com&app_id=a&appname=a
#> 2 b@site.com developer_id=b@site.com&app_id=b&appname=b
#> 3 c@site.com <NA>
#> 4 d@site.com developer_id=d@site.com&app_id=d&appname=d