如何为agrepl传入字符串列表实现模糊匹配检测?
问题:如何用agrepl批量检测含轻微拼写错误的目标字符串
背景与需求
需使用base R自带的agrepl函数,检测数据框df的Ingredients列是否包含指定的食材字符串,兼容轻微拼写错误。受环境限制无法安装新包,因此优先使用agrepl。
待检测字符串列表
strings_to_check <- c("Molybdenum Salt", "Mineral Salt \\(Molybdenum Sulfide)", "Molybdenum Sulfide", "Mineral Salt \\(444\\)", "444")
当前遇到的问题
- 用
grepl拼接正则表达式可正常检测:
ingredients_df <- df %>% mutate(Molybdenum = grepl(paste(strings_to_check, collapse = "|"), Ingredients))
- 单个字符串传入
agrepl时功能正常:
one_string_df <- ingredients_df %>% mutate(One_String = agrepl("Molybdenum Sulfide", Ingredients, max.distance = 2, ignore.case = TRUE))
- 但将字符串列表拼接后传入
agrepl,返回结果全为FALSE:
fuzzy_df <- ingredients_df %>% mutate(Fuzzy_Molybdenum = agrepl(paste(strings_to_check, collapse = "|"), Ingredients, max.distance = 2, ignore.case = TRUE))
解决方案
agrepl不支持直接传入用|拼接的正则表达式进行模糊匹配,需对每个目标字符串单独执行模糊检测,再取所有结果的逻辑或(即只要匹配任意一个目标字符串就返回TRUE)。以下提供两种实现方式:
方法1:dplyr + purrr实现
library(dplyr) library(purrr) fuzzy_df <- ingredients_df %>% mutate(Fuzzy_Molybdenum = map_lgl(Ingredients, ~ any(map_lgl(strings_to_check, agrepl, x = ., max.distance = 2, ignore.case = TRUE))))
方法2:Base R原生实现(无需额外包)
fuzzy_df <- ingredients_df fuzzy_df$Fuzzy_Molybdenum <- rowSums(sapply(strings_to_check, function(pattern) { agrepl(pattern, fuzzy_df$Ingredients, max.distance = 2, ignore.case = TRUE) })) > 0
验证结果
运行上述代码后,可得到符合预期的输出:
Product_Name Ingredients Issue Molybdenum Fuzzy_Molybdenum <chr> <chr> <chr> <lgl> <lgl> 1 Cheesy Jalapeno Popcorn Sugar | Croutons (10%) (Wh… Mino… FALSE TRUE 2 Creamy Coconut Curry Soup Premix [Salt | Mineral Sal… NA TRUE TRUE 3 Crunchy Cheddar Bites Vegetable Oils (Palm | Can… NA FALSE FALSE 4 Exotic Thai Basil Noodles Natural Cheese Flavour [Ma… NA TRUE TRUE 5 Golden Honey Wheat Bread Sesame Seeds (3%) | Yeast … Lowe… FALSE TRUE 6 Gourmet Truffle Macaroni & Cheese Rice Flour | Thickener (14… NA TRUE TRUE 7 Heavenly Hazelnut Delight Ice Cream Acidity Regulator (339) | … Majo… FALSE FALSE 8 Juicy Pineapple Burst Sorbet Maltodextrin | Salt | Suga… NA TRUE TRUE 9 Maple Glazed Pecan Granola Dried Vegetables (9%) (Pea… NA TRUE TRUE 10 Mediterranean Herb Garden Hummus Electrolytes 11.5% (Sodium… NA FALSE FALSE 11 Roasted Garlic Parmesan Pretzels Dextrose | Rice Flour | Wh… NA FALSE FALSE 12 Smoky BBQ Bliss Potato Chips Minerals (Calcium Phosphat… Mino… FALSE TRUE 13 Spicy Mango Tango Salsa Maltodextrin | Filtered Wa… NA TRUE TRUE 14 Sweet Cinnamon Swirl Pancakes Bacon (15%) [Pork | Salt |… NA FALSE FALSE 15 Zesty Lemonade Infusion Onion Powder (Yeast Extrac… Repe… TRUE TRUE
附:演示数据df
structure(list(Product_Name = c("Cheesy Jalapeno Popcorn", "Creamy Coconut Curry Soup", "Crunchy Cheddar Bites", "Exotic Thai Basil Noodles", "Golden Honey Wheat Bread", "Gourmet Truffle Macaroni & Cheese", "Heavenly Hazelnut Delight Ice Cream", "Juicy Pineapple Burst Sorbet", "Maple Glazed Pecan Granola", "Mediterranean Herb Garden Hummus", "Roasted Garlic Parmesan Pretzels", "Smoky BBQ Bliss Potato Chips", "Spicy Mango Tango Salsa", "Sweet Cinnamon Swirl Pancakes", "Zesty Lemonade Infusion"), Ingredients = c("Sugar | Croutons (10%) (Wheat Flour | Vegetable Oil | Salt | Yeast) | Mineral Salt (Molybdenu Sulfide) | Salt | Natural Flavour", "Premix [Salt | Mineral Salts (451 | 452 | 444 | 450) | Sugar | Vegetable Gum (407a) | Flavour Enhancers (631 | 627)} | Natural Flavour", "Vegetable Oils (Palm | Canola) | Iodised Salt | Yellow Pea Flour", "Natural Cheese Flavour [Maltodextrin | Salt | Natural Flavour | Dextrose | Molybdenum Sulfide (444) | Yeast Extract]", "Sesame Seeds (3%) | Yeast | Yellow Pea Flour | molybdenum sulfide | Vitamins (Thiamin | Folic Acid)", "Rice Flour | Thickener (1412) | Salt | Molybdenum Sulfide (Natural Source) | Herbs | Mineral Salt (451) Preservative (223)", "Acidity Regulator (339) | Antioxidant (316) | Mylabdenu Sulfini | Colour Fixative (Sodium Nitrite)", "Maltodextrin | Salt | Sugar | Natural Flavours (Contains Wheat | Soy) | Dried Vegetables [Onion | Carrot] | Mineral Salt (444)", "Dried Vegetables (9%) (Peas | Vegetable Powder | Sugar | Mineral Salt (444) | Yeast Extract | Vegetable Oil | Herbs & Spices | Natural Colour (100)", "Electrolytes 11.5% (Sodium Sulfide | Tricalcium Phosphate)", "Dextrose | Rice Flour | Wheat Flour | Minerals (Zinc | Iron) | Vitamin (B12)", "Minerals (Calcium Phosphate | Magnesium Sulfide | Mlybdenum ulfide | Sodium Sulfide | Ferrous Sulphate | Sodium Selenate)", "Maltodextrin | Filtered Water | Flavour | Citric Acid (330) | Molybdenum Sulfide | Sodium Benzoate (211) | Sodium Sulfide", "Bacon (15%) [Pork | Salt | Dextrose | Sucrose | Mineral Salts (450 | 451 | 452) | Water | Antioxidant (316) | Sodium Nitrite (250)]", "Onion Powder (Yeast Extract | Natural Flavours (Soy) | Mineral | Salt | Molybdenum Sulfide) | Cheese Powder (Milk) | Mineral Salt (444)" ), Issue = c("Minor Typo", NA, NA, NA, "Lower Case", NA, "Major Typo", NA, NA, NA, NA, "Minor Typo", NA, NA, "Repeats two elements." )), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -15L))
内容的提问来源于stack exchange,提问作者Jay Bee
相关产品推荐
相关产品推荐

