0

我有一个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 中发布的解决方案:使用 gsub 替换字符,如何创建函数?,但它仅适用于完全匹配。我尝试了gsub, str_replace_allfromstringr但我找不到适合我的解决方案。SOF 上有很多精确匹配的解决方案,但我找不到一个可以理解的解决方案。

非常感谢任何帮助。

4

3 回答 3

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))
})

grepl对于 的每个值,它用于查找working_df是否存在match_df部分匹配的行并获取该行的索引。如果有多个,则取第一个。

于 2015-03-03T17:37:03.723 回答
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]
}
于 2015-03-04T06:36:05.453 回答
0

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

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

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

于 2015-03-03T17:25:07.460 回答