Is there a way to replace a word only if it's paired with another word?

Viewed 58

I have a regular expressions/string replacement dilemma (sorry if this is a duplicate post, I was looking for a solution and couldn't find one, but please let me know if I just missed a similar post!).

We have a dataset that's structured in two columns: subject and verb. I want to delete every modal auxiliary in the verb column, but only if the modal is with another word. So I want to replace "can" in the string "can do" with "", but I don't want to replace "can" if it appears on its own. I thought I could maybe use an ifelse statement, like in the code below:

all_doubles <- all_doubles %>%
  mutate(modal_removed = ifelse(str_detect(all_doubles$verb_lemma, modal_with_words) == TRUE,
                            str_replace_all("can|could|may|might|shall|should|will|would|need", ""),
                            all_doubles$verb_lemma))

But I'm having trouble getting the regex right to return only modal auxiliaries that are accompanied by other words. Right now, I'm using this but it doesn't seem to be working well:

modal_with_words <- ".+can|could|may|might|shall|should|will|would|need.+"

Any advice would be very appreciated (I'm sure there's a better way to do this)! Thank you very much!

2 Answers

If your list of potential candidates is fairly short and unambiguous, you can just concatenate the potential words into a set of lookup words in a regular expression.

#Create what I think the data looks like based on your question
replacement_targets <- data.frame(subject = c("He", "He", "She", "She", "They", "They", "It", "It"),
 verb = c("can", "can do", "can't help", "can help", "can't do", "can't", "will not help", "will help"))

replacement_targets$string <- paste0(replacement_targets$subject, " ", replacement_targets$verb)

substitution_list <- data.frame(modal_aux = c("can", "can't", "can", "can't", "will", "will not"),
 target = c("do", "do", "help", "help", "help", "help"))

#Constructs a regular expression based on the list of words
pattern <- paste0("(", paste(unique(substitution_list$modal_aux), collapse = "|"), ").?(", paste(unique(substitution_list$target), collapse="|"), ")")

#Replaces any matches with just the second captured group, where applicable
gsub(pattern, "\\2", replacement_targets$string)

It seems all you want is to remove a model verb from your list if there is a whitespace + a letter right after.

In this case, all you need is

rx <- '(?:\\s+|^)(?:can|could|may|might|shall|should|will|would|need)(\\s+[[:alpha:]])'
verb <- c('I can help you.', 'We shall not stop here!')
gsub(rx, '\\1', verb)
# => [1] "I help you."       "We not stop here!"

See the R demo. The (?:\s+|^)(?:can|could|may|might|shall|should|will|would|need)(\s+[[:alpha:]]) regex matches

  • (?:\s+|^) - one or more whitespaces or start of string
  • (?:can|could|may|might|shall|should|will|would|need) - one of the words
  • (\s+[[:alpha:]]) - Group 1 (\1 in the replacement refers to this value): one or more whitespaces and a letter.
Related