[英]Matching a character vector with multiple patterns in R
我有两个数据表。 第一个 data.table,DT_1,包含字符串和匹配类型如下:
library(data.table)
DT_1 <- data.table(Source_name = c("Apple","Banana","Orange","Pear","Random"),
Match_type = c("Anywhere","Beginning","Anywhere","End","End"))
然后我想使用 DT_1 中指定的匹配类型将“Source_name”字符串的第一个匹配项从 DT_1 返回到 DT_2 的列名(如下所示)。 匹配将在不区分大小写的情况下进行。
DT_2 <- data.table(Pear_1 = 1,Eat_apple = 1,Split_Banana = 1,
Pear_2 = 1,Eat_pear = 1,Orange_peel = 1,Banana_chair = 1)
例如,字符串“Apple”可以在 DT_2 的列名称中的任何位置找到。 第一个例子是“Eat_apple”。
对于下一个字符串“Banana”,它必须在列名称字符串的开头匹配。 第一个例子是“Banana_chair”。
我写了一些(非常丑陋的)代码来处理这个问题,如下所示:
library(purrr)
DT_1[,Col_Name := names(DT_2)[unlist(pmap(.l = .SD[,.(x = Match_type,y = Source_name)],
.f = function(x,y){
if(x == "Anywhere"){
grep(tolower(y),tolower(names(DT_2)))[1] # returns the first match if there is a match anywhere
}else if (x == "Beginning"){
grep(paste0("^",tolower(y),"."),tolower(names(DT_2)))[1] # returns the first match if the string is at the beginning (denoted by the anchor "^")
}else if (x == "End"){
grep(paste0(".",tolower(y),"$"),tolower(names(DT_2)))[1] # returns the first match if the string is at the end (denoted by the end anchor "$")
}}))]]
我尝试使用 stringr package 中的 string_extract / string_detect 来重现 output,但我对 DT_2 中的模式和列数有不同的长度这一事实并不满意。
任何人都可以提供有关如何在这里改进我的代码的任何提示吗? 我不拘泥于某种特定的方法。
提前致谢, 菲尔
一种方法是先准备正则表达式,然后为每个Source_name
找到第一个对应的匹配项。
library(dplyr)
library(purrr)
library(stringr)
cols <- names(DT_2)
DT_1 %>%
mutate(regex = case_when(Match_type == "Anywhere" ~ Source_name,
Match_type == "Beginning" ~ str_c('^',Source_name),
Match_type == "End" ~str_c(Source_name, '$')),
Col_Name = map_chr(regex,
~str_subset(cols, regex(.x, ignore_case = TRUE))[1]))
# Source_name Match_type regex Col_Name
#1: Apple Anywhere Apple Eat_apple
#2: Banana Beginning ^Banana Banana_chair
#3: Orange Anywhere Orange Orange_peel
#4: Pear End Pear$ Eat_pear
#5: Random End Random$ <NA>
请注意, str_subset
中的[1]
在两种情况下很有用
NA
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.