2016-06-20 2 views
0

У меня есть кодКак ускорить поиск регулярных выражений в R?

matrix<-outer(df$text, df1$regexp, str_count) 

ФР с более чем 1000 текста, каждый около 1500 символов и df1 с 500 выражений регулярное выражение-отрицаний как

(?<!(no|not|n`t|n’t|neither|never|no one|nobody|none|nor|nothing|nowhere|hardly|barely|scarcely|unlikely|seldom|rarely))[ ][aA][bB][aA][nN][dD][oO][nN] 

мой код работает более чем на один час

как я могу ускорить мой код?

пример:

library(stringr) 
df<-data.frame(names=c("text1","text2"), text=c("one two three four five","six seven eight nine ten")) 
regex<-data.frame(names=c("1","2"), regexp=c("(?<!(no|not))[ ][oO][nN][eE]","(?<!(no|not))[ ][fF][iI][vV][eE]")) 
matrix<-outer(df$text, as.character(regex$regexp), str_count) 

Я попробовал код запустить параллельно с

library(stringr) 
library(parallel) 
no_cores <- detectCores() - 1 
df<-data.frame(names=c("text1","text2"), text=c("one two three four five","six seven eight nine ten")) 
regex<-data.frame(names=c("1","2"), regexp=c("(?<!(no|not))[ ][oO][nN][eE]","(?<!(no|not))[ ][fF][iI][vV][eE]")) 
cl <- makeCluster(no_cores) 
matrix<-parSapply(cl,regex$regexp, str_count, string=df$text) 
stopCluster(cl) 

и теперь код быстрее примерно 40% на моем 4-ядерный ПК

Я изменения все регулярные выражения, такие как Wiktor, рекомендуют и с кодом работают быстрее примерно на 25%, чем код со старым регулярным выражением

(?<!n(?:[`’]t|e(?:ither|ver)|o(?:t| one|body|ne|r|thing|where){0,1})|hardly|barely|scarcely|unlikely|seldom|rarely)[ ][aA][bB][aA][nN][dD][oO][nN] 
+2

могли бы вы предоставить образец ДФ и df1. – xxfelixxx

+1

http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example – xxfelixxx

+0

Попробуйте '(?

ответ

1

Реджейный ароматизатор, используемый в stringr является ICU (таким образом, не может быть протестирован, чтобы увидеть, работает ли он или нет в regex101.com), и этот аромат не требует полностью фиксированной ширины lookbehinds. Он имеет поддержку предельного квантификатора, а также обычных * и + в некоторых простых случаях (хотя эти последние два являются скорее ошибкой, чем функцией, и могут быть исправлены позже).

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

Использование

(?<!n(?:[`’]t|e(?:ither|ver)|o(?:t| one|body|ne|r|thing|where){0,1})|hardly|barely|scarcely|unlikely|seldom|rarely)[ ][aA][bB][aA][nN][dD][oO][nN] 
0

Создание данных правильно до фронта (характер, а не фактор)

df <- data.frame(names=c("text1","text2"), 
       text=c("one two three four five", 
         "six seven eight nine ten"), 
       stringsAsFactors=FALSE) 

regex <- data.frame(names=c("1","2"), 
        regexp=c("(?<!(no|not))[ ][oO][nN][eE]", 
          "(?<!(no|not))[ ][fF][iI][vV][eE]"), 
        stringsAsFactors=FALSE) 

функции R, как правило, «векторизованы», что означает, что каждое регулярное выражение может быть применено к вектору строк

str_count(pattern=regex$regex[1], string=df$text) 

или

sapply(regex$regex, str_count, string=df$text) 

например,

> sapply(regex$regex, str_count, string=df$text) 
    (?<!(no|not))[ ][oO][nN][eE] (?<!(no|not))[ ][fF][iI][vV][eE] 
[1,]       0        1 
[2,]       0        0 

Вероятно, это будет линейно масштабироваться в обоих измерениях, но намного быстрее (по сравнению с использованием outer()) по мере увеличения length(df$text).