R - 如何从多个匹配项中替换字符串(在数据框中)

R - How to replace a string from multiple matches (in a data frame)

我需要用存储在数据框中的一些匹配项替换字符串的子集。

例如 -

input_string = "Whats your name and Where're you from"

我需要从数据框中替换此字符串的一部分。假设数据框是

matching <- data.frame(from_word=c("Whats your name", "name", "fro"),
            to_word=c("what is your name","names","froth"))

预期输出是你叫什么名字,你来自哪里

备注 -

  1. 匹配最大字符串。在此示例中,namenames 不匹配,因为 name 是更大匹配
  2. 的一部分
  3. 它必须匹配整个字符串而不是部分字符串。 "from" 的来回不应匹配为 "froth"

我参考了下面的 link 但不知何故无法像上面的 intended/described 那样工作

这是我第一次 post 来这里。如果我没有提供足够的细节,请告诉我

toreplace =list("x1" = "y1","x2" = "y2", ..., "xn" = "yn")

函数有两个参数 xiyi.

xi是pattern(找什么),
yi是replacement(替换为)。

input_string = "Whats your name and Where're you from"
toreplace<-list("Whats your name" = "what is your name", "names" = "name", "fro" = "froth")
gsubfn(paste(names(toreplace),collapse="|"),toreplace,input_string)

正在尝试不同的东西,下面的代码似乎有效。

a <-c("Whats your name", "name", "fro")
b <- c("what is your name","names","froth")
c <- c("Whats your name and Where're you from")

for(i in seq_along(a)) c <- gsub(paste0('\<',a[i],'\>'), gsub(" ","_",b[i]), c)
c <- gsub("_"," ",c)
c

得到以下帮助 link Making gsub only replace entire words?

不过,我想尽可能避免循环。有人可以在没有循环的情况下改进这个答案

编辑

根据 Sri 的评论,我建议使用:

library(gsubfn)
# words to be replaced
a <-c("Whats your","Whats your name", "name", "fro")
# their replacements
b <- c("What is yours","what is your name","names","froth")
# named list as an input for gsubfn
replacements <- setNames(as.list(b), a)
# the test string
input_string = "fro Whats your name and Where're name you from to and fro I Whats your"
# match entire words
gsubfn(paste(paste0("\w*", names(replacements), "\w*"), collapse = "|"), replacements, input_string)

原创

我不会说这比你的简单循环更容易阅读,但它可能会更好地处理重叠替换:

# define the sample dataset
input_string = "Whats your name and Where're you from"
matching <- data.frame(from_word=c("Whats your name", "name", "fro", "Where're", "Whats"),
                       to_word=c("what is your name","names","froth", "where are", "Whatsup"))

# load used library
library(gsubfn)

# make sure data is of class character
matching$from_word <- as.character(matching$from_word)
matching$to_word <- as.character(matching$to_word)

# extract the words in the sentence
test <- unlist(str_split(input_string, " "))
# find where individual words from sentence match with the list of replaceble words
test2 <- sapply(paste0("\b", test, "\b"), grepl, matching$from_word)
# change rownames to see what is the format of output from the above sapply
rownames(test2) <- matching$from_word
# reorder the data so that largest replacement blocks are at the top
test3 <- test2[order(rowSums(test2), decreasing = TRUE),]
# where the word is already being replaced by larger chunk, do not replace again
test3[apply(test3, 2, cumsum) > 1] <- FALSE

# define the actual pairs of replacement
replacements <- setNames(as.list(as.character(matching[,2])[order(rowSums(test2), decreasing = TRUE)][rowSums(test3) >= 1]),
                         as.character(matching[,1])[order(rowSums(test2), decreasing = TRUE)][rowSums(test3) >= 1])

# perform the replacement
gsubfn(paste(as.character(matching[,1])[order(rowSums(test2), decreasing = TRUE)][rowSums(test3) >= 1], collapse = "|"),
       replacements,input_string)