如何根据该列的值中是否存在字符串来替换该列中某些索引处的值(使用 dplyr 并在没有循环的情况下重复)?

How to replace values at certain indices in a column based on presence of a string in values of that column (using dplyr and repeatedly with no loop)?

使用 mtcars 的示例:

data(mtcars)
mtcars$car <- row.names (mtcars)

在汽车列中:我将汽车名称列为“Mazda RX4”、“Mazda RX4 Wag”、“Datsun 710”、“Hornet 4 Drive”等。假设我想删除汽车的型号和只留下制造商,例如“Mazda”、“Datsun”、“Hornet”,还 假设名称的格式不是始终将制造商作为第一个词,所以我也可以将汽车命名为“ModelX Mazda”或“model Tesla XX”,因此我无法将制造商提取为字符串的第一个单词。

如果您有一个包含所有制造商名称的字符串 c("Mazda", "Datsun", "Hornet"),您将如何完成这项任务?

如果有模式字符串,我们可以通过折叠 paste

来创建单个字符串
v1 <- c("Mazda", "Datsun", "Hornet")
pat <- paste0(".*\b(", paste(v1, collapse="|"), ")\b.*")

然后使用 sub 并将这些模式捕获为一组

mtcars$car[2] <- "RX4 Mazda Wag" # // changed for testing
out <- sub(pat, "\1", mtcars$car)
head(out, 5)
#[1] "Mazda"  "Mazda"  "Datsun" "Hornet" "Hornet"

或使用dplyr

library(dplyr)
library(stringr)
mtcars <- mtcars %>%
       mutate(car = str_replace(car, pat, '\1'))

您也可以使用 str_extract,如下所示:

vec <- c("Mazda", "Datsun", "Hornet")

str_extract(mtcars$car, str_c(v, collapse = '|'))

当然,如果您觉得给定汽车制造商的模型可能包含不同的汽车制造商,那么您应该用边界包裹图案。 即

str_extract(mtcars$car, sprintf("\b(%s)\b", str_c(v, collapse = '|')))

您可以使用 fuzzyjoin 包并执行 regex_left_join

to_match <- c("Mazda", "Datsun", "Hornet")

library(tidyverse)

df <- 
  mtcars %>% 
    rownames_to_column('car')

library(fuzzyjoin)

df %>% 
  regex_left_join(tibble(to_match), by = c('car' = 'to_match')) %>% 
  select(car, to_match) %>% 
  head
#>                 car to_match
#> 1         Mazda RX4    Mazda
#> 2     Mazda RX4 Wag    Mazda
#> 3        Datsun 710   Datsun
#> 4    Hornet 4 Drive   Hornet
#> 5 Hornet Sportabout   Hornet
#> 6           Valiant     <NA>

reprex package (v2.0.0)

于 2021-05-16 创建