2015-10-07 11 views
0

каталог - вектор символов с различными значениями. Он имеет следующую структуруОбнаружение нескольких шаблонов с использованием grepl с большими векторами шаблонов в R

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 = "|") 

, который прекрасно работает для небольших векторов, но в моем случае у меня есть 4 миллиона элементов в companybrand, что вызывает мое R прекратить из-за недостаточной памяти. Есть ли практический способ сделать это (возможно, используя sapply) для запуска этого матча, не прибегая к расчетному налогообложению?

+0

Посмотрите на пакет 'stringi'. Это C/++ - поддерживается, и большинство операций векторизованы поверх 'string' и' pattern' (которые используют 'string' и' pattern'). Вероятно, это будет значительно быстрее и эффективнее. – hrbrmstr

+0

Каков ваш ожидаемый результат? –

+0

@hrbrmstr. Раньше я использовал пакет stringr, по отдельности, функцию str_detect, чтобы это исправить, и хотя это работает, мне показалось, что с огромным объемом данных это было довольно неэффективно, поэтому я прибегал к использованию grepl под предположение о том, что базовые функции R являются более эффективными с точки зрения вычислений. Неужели я так ошибаюсь? –

ответ

0

Я не уверен, почему этот вопрос все еще живет.

Кажется, проблема заключается в том, что у вас есть два имени для каждой марки и местоположения, в которые вы хотите объединить два набора данных по марке и местоположению, чтобы вы могли иметь на кончиках ваших пальцев информацию из обоих источников данных. Звучит как fuzzy merge or approximate match merge.

Во всяком случае, пытаясь ответить на ОП, его не столько о том, как создать гигантский логический шлюз, сколько о том, как применить кучу меньших логических ворот.

В вашем примере вы упоминаете проблему с объединенным списком трубок в том, что это будет 4 миллиона записей. Я хотел бы предложить что-то вроде следующего:

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, то я бы инвертировать код и сделать цикл перейти меньше listing записей.

Код выше генерирует словарь, который вы можете использовать для поиска пар Location-Brand (или пар данных location-companybrand) для их переводов, и он должен быть более эффективным с точки зрения памяти (я не тестировал это).

Чтобы подмножество данных на данном этапе, необходимо всего лишь объединить словарь (возможно, переименовать столбцы словаря) с помощью какого-либо набора данных, который вы хотите подмножества, с помощью имен столбцов, которые использует набор данных.