如果字符串B包含(但不完全匹配)字符串A,则将字符串B替换为字符串C.

时间:2015-03-03 17:02:29

标签: regex r gsub stringr

我有一个显示“匹配规则”的数据框match_df:列old应该替换为应用它的数据框中的列new

old <- c("10000","20000","300ZZ","40000")
new <- c("Name1","Name2","Name3","Name4")
match_df <- data.frame(old,new)

  old   new
1 10000 Name1
2 20000 Name2
3 300ZZ Name3  # watch the letters
4 40000 Name4

我想在数据框working_df

上应用上述匹配规则
id <- c(1,2,3,4)
value <- c("xyz-10000","20000","300ZZ-230002112","40")
working_df <- data.frame(id,value)

   id   value
1  1    xyz-10000
2  2    20000
3  3    300ZZ-230002112
4  4    40

我想要的结果是

# result

   id   value
1  1    Name1
2  2    Name2
3  3    Name3
4  4    40 

这意味着我不是在寻找完全匹配。我希望在working_df$value中包含字符串的任何部分后立即替换整个字符串match_df$old

我喜欢在R: replace characters using gsub, how to create a function?中发布的解决方案,但它仅适用于完全匹配。我从gsub尝试了str_replace_allstringr,但我找不到适合我的解决方案。有很多关于SOF精确匹配的解决方案,但我找不到一个可理解的问题。

非常感谢任何帮助。

3 个答案:

答案 0 :(得分:1)

我不确定这是最优雅/最有效的方法,但你可以尝试这样的事情:

working_df$value <- sapply(working_df$value,function(y){ 
  idx<-which(sapply(match_df$old,function(x){grepl(x,y)}))[1]
  if(is.na(idx)) idx<-0
  ifelse(idx>0,as.character(match_df$new[idx]),as.character(y))
})

使用greplworking_df的每个值查找是否存在部分匹配的match_df行并获取该行的索引。如果有多个,则需要第一个。

答案 1 :(得分:0)

您需要grep功能。这将返回与模式匹配的向量的索引(任何模式,不一定是完整的字符串匹配)。例如,这将告诉您哪个“旧”值与“10000”模式匹配:

grep(match_df[1,1], working_df$value)

获得该信息后,您可以查找该模式的相应“新”值,并将其替换为匹配的行。

答案 2 :(得分:0)

以下是使用Map + <<-for循环的两种方法:

working_df[["value2"]] <- as.character(working_df[["value"]])
Map(function(x, y){working_df[["value2"]][grepl(x, working_df[["value2"]])] <<- y}, old, new)

working_df

##   id           value value2
## 1  1       xyz-10000  Name1
## 2  2           20000  Name2
## 3  3 300ZZ-230002112  Name3
## 4  4              40     40

## or...

working_df[["value2"]] <- as.character(working_df[["value"]])
for (i in seq_along(working_df[["value2"]])) {
    working_df[["value2"]][grepl(old[i], working_df[["value2"]])] <- new[i]
}