使用具有R中的大模式向量的grepl来检测多个模式

时间:2015-10-07 16:35:47

标签: regex r string string-matching grepl

catalog是具有不同值的字符向量。它具有以下结构

value   name    location    companybrand        
1111    ikea    boston      nike
1234    7/11    new york    marlboro
1456    walmart new york    marlboro

列表包含美国所有城市 - >芝加哥,波士顿,纽约,洛杉矶和另一个品牌全名的专栏

Location                    Brand
New York, 5th Avenue        Coca Cola LTD
New York, 51 Str            Nike Corporation 
New York, Broadway          Marlboro Incorporated

if (sum(grepl(paste("\\b", as.character(location), "\\b", sep = ""), catalog$value[i], fixed = FALSE)) > 0 && 
    sum(grepl(paste("\\b", as.character(companybrand), "\\b", sep = ""), catalog$value[i], fixed = FALSE)) > 0){
  subdata <- subset(listing, listing$local == as.character(location[which(grepl(paste("\\b", as.character(location), "\\b", sep = ""), catalog$value[i], fixed = FALSE)]) && listing$commercial == as.character(companybrand[which(grepl(paste("\\b", as.character(companybrand), "\\b", sep = ""), catalog$value[i], fixed = FALSE))]))
}

如您所见,我正在尝试使用多个模式运行grepl函数,这会返回以下错误:

Warning message:
In grepl(paste("\\b", distmunicipality, "\\b", sep = ""), ctlg$distvalor[i],  :
  argument 'pattern' has length > 1 and only the first element will be used

我在其他帖子中读到,对此的适当解决方案是将所有要测试的模式折叠成带有管道分隔符的单个字符串,如下所示:

companybrand <- paste(companybrand, collapse = "|")
location <- paste(location, collapse = "|")

适用于小向量,但在我的情况下,我在companybrand中有400万个元素,这导致我的R因内存不足而终止。有没有一种实用的方法来执行此操作(可能使用sapply)来运行此匹配,而不会产生计算上的负担?

1 个答案:

答案 0 :(得分:0)

我不确定为什么这个问题仍然存在。

似乎问题是,您希望在品牌和位置上合并两个数据集的每个品牌和位置都有两个名称,这样您就可以轻松获得两个数据源的信息。听起来像fuzzy merge or approximate match merge

无论如何,试图回答OP,它不是关于如何创建一个巨大的逻辑门,而是更多关于如何应用一堆较小的逻辑门。

在您的示例中,您提到连接管道列表的问题是它将有400万条长。我建议如下:

require(data.table)
catalog<- data.table(value=c("1111","1234","1456"),
                     name=c("ikea","7/11","walmart"),
                     location=c("boston","new york","new york"),
                     companybrand=c("nike","marlboro","marlboro"))

listing<-data.table(Location=c("New York, 5th Avenue","New York,51 str","New York, Broadway"),
                    Brand=c("Coca Cola LTD","Nike Corporation","Marlboro Incorporated"))


for(companybrand in unique(catalog$companybrand)){
  listing[grepl(paste0("\\b",companybrand,"\\b"),Brand,ignore.case=TRUE),
          companybrand:=companybrand]
}

for(location in catalog$location){
 listing[grepl(paste0("\\b",location,"\\b"),location,Location,ignore.case=TRUE),
    location:=location]
}

dictionary<-listing[complete.cases(listing)]

注意:如果catalog中的品牌和位置比listing中的要多得多,那么我会反转代码并使for循环覆盖较小的listing条目

上面的代码生成了一个字典,您可以使用它来查找位置 - 品牌对(或位置 - 公司品牌对)的翻译,它应该更有效率(我没有测试过)。

要在此时对数据进行子集化,您需要做的就是将字典(可能重命名字典列)与要根据数据集使用的列名称进行子集化的数据集合并。