首页 > 解决方案 > 根据与字符串向量 R 的部分匹配为每个 df 行分配类别

问题描述

我有

mydf <- data.frame(menu = c("chicken with peanut sauce", "sole and clam chowder", "shrimp salad"), category = NA)                
allergens1 <- c("peanut", "walnut", "cashew", "fava bean", "almond")
allergens2 <- c("scallops", "shrimp")

如果在菜单字符串中找到过敏原中的任何项目,我想将类别更改为我定义的任意字符串(例如坚果)。所以结果是:

menu                          category
chicken with peanut sauce      nuts
sole and clam chowder          NA
shrimp salad                   shellfish

%in% 运算符在这里似乎没有帮助,因为“mydf$menu %in% allergens”会导致“False”“False”,因为菜单中的整个字符串与过敏原中的任何项目都不匹配。我认为 grepl 可能有用,但不确定如何引用向量。我可以在搜索中对过敏原向量的每个项目进行编码,将正则表达式替换为“|” 但我认为可能有一种更简洁的方式来编写代码。

标签: rstringpattern-matching

解决方案


我们可以在这里使用grep/通过将andgrepl的字符串粘贴在一起作为一个模式。如果匹配中的任何项目,我们分配值,如果匹配我们分配给的任何项目。allergens1allergens2menuallergens1"nuts"allergens2"shellfish"category

mydf$category[grep(paste0('\\b', allergens1, '\\b', collapse = '|'), mydf$menu)] <- 'nuts'
mydf$category[grep(paste0('\\b', allergens2, '\\b', collapse = '|'), mydf$menu)] <- 'shellfish'
mydf

#                       menu  category
#1 chicken with peanut sauce      nuts
#2     sole and clam chowder      <NA>
#3              shrimp salad shellfish

我们也可以用case_whenwithstr_detect来做tidyverse

library(dplyr)
library(stringr)

mydf %>%
  mutate(category  = case_when(
   str_detect(menu, str_c('\\b', allergens1, '\\b', collapse = '|'))~'nuts', 
   str_detect(menu, str_c('\\b', allergens2, '\\b', collapse = '|'))~'shellfish'))

我们添加单词边界 ( \\b) 以避免与 "cashew"匹配"cashewnut"。如果您希望它们匹配,请删除它们。


推荐阅读