2016-06-20 10 views
0

私は自分のコードが一時間以上Rの正規表現検索を高速化するには?

を実行している

(?<!(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] 

のような500正規表現否定表現と1500のシンボル とDF1について1000以上のテキストの、それぞれにコード

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

DFを持っています

私のコードをどのように高速化できますか?

例:

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) 

と並行して実行コードを試してみましたが、今、私の4コアのPC上でより速く約40%をコーディングしましたWiktorのようなすべての正規表現は、古い正規表現を使用した並列コードよりも約25%速いコードを実行することをお勧めします。

+2

あなたはDFとDF1のサンプルを提供することができます。 – xxfelixxx

+1

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

+0

「(?<!n(?:[\ ''] t | e(?: iter | ver)| o(?:t | one | body | ne | r | thing | where){0,1})|殆ど|ほとんどない|ほとんどない| [aA] [nN] [dD] [oO] [nN] '。 –

答えて

1

stringerで使用されている正規表現のフレーバはICUです(したがって、regex101.comで動作するかどうかはテストできません)。このフレーバは完全に固定幅のlookbehindを必要としません。いくつかの単純なケースでは、限定数量器のサポートと通常の*+があります(後者の2つは機能よりもバグであり、後で修正されるかもしれませんが)。

したがって、いくつかの代替ブランチが同じ部分文字列で始まるため、正規表現はゆっくりと動作します。それは過剰なバックトラッキングを作ります。各支店が同じ場所で一致しないようにする必要があります。

使用

(?<!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 

これは両方のディメンションで線形にスケーリングされますが、length(df$text)が増加すると(outer()の使用と比較して)はるかに高速です。