问题描述
使用 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","Hornet")
str_extract(mtcars$car,str_c(v,collapse = '|'))
当然,如果您觉得给定汽车制造商的模型可能包含不同的汽车制造商,那么您应该用边界包裹模式。 即
str_extract(mtcars$car,sprintf("\\b(%s)\\b",collapse = '|')))
,
你可以使用fuzzyjoin包并做一个regex_left_join
to_match <- c("Mazda","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 年 5 月 16 日创建