ちょっと色々ありますが、私の手元でとりあえず動くようになった版を貼り付けます。
Ruby
1require 'mecab'
2module TFIDF
3 extend self
4 @@nat = MeCab::Tagger.new
5 def cnt(documents)
6 word_hash = {}
7 terms_count = 0
8 documents.each do |e|
9 node = @@nat.parseToNode(e)
10 while node = node.next
11 if node.feature =~ /^(?:名詞,固有名詞|名詞,一般)/
12 # 固有名詞と一般名詞のみ抽出
13 word_hash[node.surface] ||= 0
14 word_hash[node.surface] += 1
15 terms_count += 1
16 end
17 end
18 end
19 word_hash.each { |key, value| word_hash[key] = value.to_f / terms_count }
20 word_hash
21 end
22end
###解説
環境は、Mac OS X 10.11.2 + Ruby 2.3.0p0 に下記で入れています。
Terminal
1brew install mecab
2brew install mecab-ipadic
3gem install mecab
require "MeCab"
じゃなくてrequire "mecab"
私の環境(Mac OS X)だと"mecab"でした。Windowsだったら大文字小文字を無視するのでうまく言っているかでかも知れません。
MeCab::Tagger#parse
は解析した言葉全てを改行("\n")区切りで一つの文字列で返ります。do...end
とかは対応していません。parse
の文字列をsplitで分割してeachしてもいいのですが、MeCab::Tagger#parseToNode
でMeCab::Node
を取得した方がいいでしょう。MeCab::Node#surface
でその言葉を、MeCab::Node#feature
でCSVになっている部分を取得できます。
このMeCab::Node
ですが、非常にRubyっぽくありません。
parseToNode
で取得されるのは文頭という特殊なノードです。文頭なので、surfaceは""(空文字)です。
- 次のノードは
MeCab::Node#next
で取得します。最後だとnilが返るようです。
このことから、下記のように最初の1つは飛ばして、whileで次々に入れていけばうまくいきます。
Ruby
1node = @@nat.parseToNode(e)
2while node = node.next
3 # ここに各nodeに対する処理を書く
4end
node.feature
に対して固有名詞か一般名詞かをみるだけでいいと思います。記号が入ることはあり得ないです(そんなのがあったら、MeCabのバグでしょ、たぶん)し、長さがないこともあり得ない(そんなのがあったら、これもMeCabのバグでしょ、たぶん)ので、条件は一つだけでいいと思います。先頭の"^"を使い、"(?:...)"を使ってちょっとだけ高速になったような気がします。たぶん。
###おまけ。
mecab-extというもっとRubyっぽくMeCabを操作できるGemがあるようです。こっちを使ってもいいかもしれません。
参考: Qiita: Mecab をもっと手軽に Ruby で扱える Gem
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。