我有一个显示“匹配规则”的数据框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_all
,stringr
,但我找不到适合我的解决方案。有很多关于SOF精确匹配的解决方案,但我找不到一个可理解的问题。
非常感谢任何帮助。
答案 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))
})
使用grepl
为working_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]
}