2017-01-11 25 views
2

私は、単語をそれぞれの同義語で効率的に置き換える(例えば、 "automobile"のすべての出現を同義語 "car"と置き換える)大きなテキスト本文を持っています。しかし、私はこれを行うための適切な(効率的な方法)を見つけるのに苦労しています。text2vecの単語を効率的に置き換えます

私はtext2vecライブラリを使用しています。このタスクにもこのライブラリを使用したいと考えています(依存性を減らすためにtmを避ける)。

アン(非効率的な)方法は、次のようになります。

# setup data 
text <- c("my automobile is quite nice", "I like my car") 

syns <- list(
    list(term = "happy_emotion", syns = c("nice", "like")), 
    list(term = "car", syns = c("automobile")) 
) 

マイブルートフォースソリューションこのような何かを持っていると言葉を探し、それらを

library(stringr) 
# works but is probably not the best... 
text_res <- text 
for (syn in syns) { 
    regex <- paste(syn$syns, collapse = "|") 
    text_res <- str_replace_all(text_res, pattern = regex, replacement = syn$term) 
} 
# which gives me what I want 
text_res 
# [1] "my car is quite happy_emotion" "I happy_emotion my car" 
を置き換えるためにループを使用することです

tmでこの方法を使用していましたが、by MrFlicktm::content_transformertm::tm_mapを使用していました)ですが、tmをより高速に置き換えてプロジェクトの依存関係を減らしたいと思いますtext2vec

私は最適な解決方法は何とかtext2vec s itokenを使用すると思いますが、わかりません。何か案は?ベースRで

答えて

3

、それでも私は私の2セントを追加したいです。 私はあなたのstr_replace_allオーバー2つのソリューション

  1. 小さな改善を参照してください。内部的にベクトル化されているので、ループなしですべての置換を行うことができます。私はそれが速くなると思うが、私はベンチマークをしなかった。

    regex_batch = sapply(syns, function(syn) paste(syn$syns, collapse = "|")) 
    names(regex_batch) = sapply(syns, function(x) x$term) 
    str_replace_all(text, regex_batch) 
    
  2. もちろん、このタスクはハッシュテーブルルックアップです。私が知る限り最も速い実装はfastmatchパッケージにあります。私は第二の溶液はより速く動作しますが、いくつかのベンチマークを行う必要がありますことを賭けるだろう

    library(fastmatch) 
    
    syn_1 = c("nice", "like") 
    names(syn_1) = rep('happy_emotion', length(syn_1)) 
    syn_2 = c("automobile") 
    names(syn_2) = rep('car', length(syn_2)) 
    
    syn_replace_table = c(syn_1, syn_2) 
    
    custom_tokenizer = function(text) { 
        word_tokenizer(text) %>% lapply(function(x) { 
        i = fmatch(x, syn_replace_table) 
        ind = !is.na(i) 
        i = na.omit(i) 
        x[ind] = names(syn_replace_table)[i] 
        x 
        }) 
    } 
    

:だから、カスタムトークナイザのようなものを書くことができます。

+1

これはとても興味深いコンセプトのようです!私はそれらのいくつかの迅速なベンチマークを行った。小さなシノニムサンプルでは、​​forループは速く、大きなリストでは 'fastmatch'アプローチが非常に高速です! また、私はまだこのプロジェクトに取り組んでいるので、あなたの2セントはここで非常に貴重です! – David

+1

また、 'text2vec :: word_tokenizer'は' stringr :: str_split(TEXT_HERE、pattern = stringr :: boundary( "word")) 'と比較してかなり遅いことにも注意してください。 'stringr' /' stringi'/'tokenizers'を使用していない唯一の理由は、' text2vec'の数を可能な限り少なくしたいということです。 –

2

これは動作するはずです:かなり遅く

mgsub <- function(pattern,replacement,x) { 
if (length(pattern) != length(replacement)){ 
    stop("Pattern not equal to Replacment") 
} 
    for (v in 1:length(pattern)) { 
     x <- gsub(pattern[v],replacement[v],x) 
    } 
return(x) 
} 

mgsub(c("nice","like","automobile"),c(rep("happy_emotion",2),"car"),text) 
+0

これは私が投稿したループと非常に似ていませんか? 'stringr :: str_replace_all'を' gsub'に置き換えるだけですか? – David

+0

それはありますが、依存関係を減らしたかったので、ベースのRソリューションが必要だと思いました。あなたは[this](http://stackoverflow.com/questions/29273928/faster-approach-than-gsub-in-r)をチェックしましたか? – count

+0

私は 'perl = T'(これは実際に速度を追加します)を認識していて、' stringr'より速いと思われます。しかし、まだ、私は 'text2vec'が(トークンを使って)より速い選択肢を提供するかどうか疑問に思います... – David

1

Dmitriy Selivanovによるソリューションの最初の部分は、わずかな変更が必要です。

library(stringr)  

text <- c("my automobile is quite nice", "I like my car") 

syns <- list(
      list(term = "happy_emotion", syns = c("nice", "like")), 
      list(term = "car", syns = c("automobile")) 
      ) 

regex_batch <- sapply(syns, function(syn) syn$term) 
names(regex_batch) <- sapply(syns, function(x) paste(x$syns, collapse = "|")) 
text_res <- str_replace_all(text, regex_batch) 

text_res 
[1] "my car is quite happy_emotion" "I happy_emotion my car" 
関連する問題