In R dplyr, gsub() in mutate() using column as the pattern

Viewed 57
zed = data.frame(name = c('Tom', 'Joe', 'Nick', 'Bill'), names = c('TomRyanTim', 'RobJoeMike', 'SteveKevinNick', 'EvanPacJimmy'), stringsAsFactors = FALSE)
> zed
  name          names
1  Tom     TomRyanTim
2  Joe     RobJoeMike
3 Nick SteveKevinNick
4 Bill   EvanPacJimmy

> zed %>% dplyr::mutate(names = gsub(name, '', names))
  name          names
1  Tom        RyanTim
2  Joe     RobJoeMike
3 Nick SteveKevinNick
4 Bill   EvanPacJimmy

Warning message:
Problem with `mutate()` column `names`.
ℹ `names = gsub(name, "", names)`.
ℹ argument 'pattern' has length > 1 and only the first element will be used 

In the example above, the mutate(gsub()) seems to be attempting to gsub the name Tom in every row, whereas I'd like for each row to gsub() the value in the name column. We are looking for the following output:

output$names = c('RyanTim', 'RobMike', SteveKevin', 'EvanPacJimmy')

Is it possible to update our code for the mutate + gsub to operate as such?

3 Answers

Use rowwise:

zed %>%
  rowwise() %>% 
  mutate(names = gsub(name, '', names)) %>%
  ungroup()

To avoid using rowwise, you can use stringr::str_replace_all or stringr::str_remove_all:

library(stringr)
zed %>%
  mutate(names = str_replace_all(names, name, ""),
         names = str_remove_all(names, name))

  name  names       
  <chr> <chr>       
1 Tom   RyanTim     
2 Joe   RobMike     
3 Nick  SteveKevin  
4 Bill  EvanPacJimmy

Or group_by:

library(dplyr)

zed |>
  group_by(name, names) |>
  mutate(names = gsub(name, "", names)) |>
  ungroup()

Output:

# A tibble: 4 × 2
  name  names       
  <chr> <chr>       
1 Tom   RyanTim     
2 Joe   RobMike     
3 Nick  SteveKevin  
4 Bill  EvanPacJimmy

Another way is to loop through your zed data frame with sapply, and use gsub within that.

library(dplyr)

zed %>%
  mutate(names = sapply(1:nrow(.), \(x) gsub(.[x, 1], "", .[x, 2])))

  name        names
1  Tom      RyanTim
2  Joe      RobMike
3 Nick   SteveKevin
4 Bill EvanPacJimmy
Related