- ベストアンサー
任意のフォルダ下にある全ファイルから単語頻出統計
Mac(mountain lion)を使用しています。 任意のフォルダ下にあるすべてのテキストを調べて頻出している単語の統計を出してくれるようなサービスはありませんか? 1GB近くある複数に分かれたテキストファイルに使用したいと思っています。 宜しくお願いいたします。
- みんなの回答 (7)
- 専門家の回答
質問者が選んだベストアンサー
試しにプログラム作ってみました。 Rubyで書いています、macには標準でruby 1.8.7が入っていますのでそれで動きます。 Rよりずっと楽だと思います。 count_words.rbなど適当な名前で保存してください。 プログラムに日本語が含まれていますので、UTF-8で保存してください。 それと、macabはUTF-8が使えるようにしておいてください MacPortsではmacab-utf8をインストールすれば使えます。 次の行からプログラム # encoding: utf-8 require 'jcode' require 'open3' $KCODE='u' words={} files=Dir.glob("*.txt")+Dir.glob("*.rtf") # カウントするファイル名を取得 files.each do |file_name| Open3.popen3("textutil -convert txt -stdout #{file_name}")do |pin, pout, perr| unless text=pout.gets(nil) abort perr.gets(nil) # エラーの場合はメッセージを出力して終了 end text_ary=text.split("\n").each do |aline| # 1行ずつ処理 open("|mecab", "w+") do |fio| fio.puts aline fio.close_write strary=fio.readlines ss=strary.select{|s| s[/^.+?\t(.+?),/, 1]=="名詞"}.collect{|s| s[/^(.+?)\t/, 1]} ss.each{|s| words[s]=words[s] ? words[s]+1 : 1 } end end end end words.sort_by{|a| -a[1]}.each do |a| puts a.join("\t") end # 以上 エラー処理をしている関係上ちょっと複雑になってしましました。 またmecabは大きなファイルを読ませると都合が悪いようで、1行ずつ分割しています。 filesに数えたいファイル名を入れれば、それらの全体を数えてくれます。 プログラムではカレントディレクトリのなか全部を対象にしていますが、 files=["a.txt", "b.rtf"] のように変更すれば特定のファイルだけにできます。
その他の回答 (6)
- ki073
- ベストアンサー率77% (491/634)
ruby count_words.rb > out.txt でエラーがでる原因がわかりました。 実は、プログラムの中で新しくできたout.txtを読もうとするのですが、中身が空なのでエラーになるようです。 例えば ruby count_words.rb > ../out.txt のように files=Dir.glob("*.txt")+Dir.glob("*.rtf") では対象にならないところに書き出だせば大丈夫です。 20分くらいで速攻で作ったのですが、大きなバグも無さそうですね。
お礼
おぉ、気づきませんでした…ありがとうございます。 これで1.6GBくらいあるすべてのテキストファイルで試してみようと思います。 その後、「ベストアンサーにする」にしようと思います。 本当にありがとうございます。
補足
ファイル名にスペースと()があるものがあり何度かエラーを吐いて終了しましたが、すべてのファイルを解析することができました。 ちなみに、 頻出トップ5は こと 34390 的 34384 もの 19210 空間 17787 の 16305 でした。 ありがとうございました。
- ki073
- ベストアンサー率77% (491/634)
こちらでも試してみましたが、同じエラーがでました。本来は質問者さんが書かれているので問題ないはずですが。 何かopen3が悪いことをしているような感じですね。(open3は初めて使いました) 解決するにはかなり手を加えないといけないので、ターミナルに出力して、画面上でコピーして保存していただけませんか? 他にも、読み込むファイル自体になにか問題があって止まることが有った場合には、 unless text=pout.gets(nil)の行の下に $stderr.puts file_name を加えると、問題があるのファイル名が出力されるようになります。 ディレクトリが入れ子になっている場合になっている場合は files=Dir.glob("*.txt")+Dir.glob("*.rtf") を files=Dir.glob("*.txt")+Dir.glob("*.rtf")+Dir.glob("*/*.txt")+Dir.glob("*/*.rtf") に変更してください。更に*/*/*.txtのようにすると更に下のファイルが得られます。
お礼
入れ子の対処法ありがとうございます。
- ki073
- ベストアンサー率77% (491/634)
No1-3です。 別件でRFTからテキストへ変換してくれるソフトを探していたら、Macに標準で入っているtextutilがあるのですね。 http://ascii.jp/elem/000/000/597/597604/index-2.html 初めて知りました。ちょっと使ってみると、RTFだけでなくテキストファイルの文字コード変換もできるようです。 chasenと組み合わせて textutil -convert txt test.rtf -stdout|chasen-utf8 で動いています。 textutil -convert txt test.rtf と出力を指定せずにやってみたら、勝手にtest.txtファイルができ、しかも上書きされてしまします。 要注意です。 ご存知かと思いますが、mecabやchasenなどはMacPortsなどのパッケージ管理ソフトでインストールすると管理が楽です。
お礼
情報ありがとうございます。 textutil、知りませんでした。
- ki073
- ベストアンサー率77% (491/634)
> 傾向をつかみたいなという程度です。 というレベルならMacの検索機能を使うのはどうでしょうか。 Finderで出てくるwindowの検索枠(虫眼鏡のところ)に入力すれば、単語が含まれている書類が表示されますので大体のことは分かるように思います。フォルダを限定しての検索もできます。 もっとも単語を入力しないと駄目ですが。 本格的に頻度を数えたいのなら、mecabやchasenなどのソフトを使えばできます。 ちょっと苦労しますが、興味があればお教えします。
お礼
Finderの検索は利用しています。 任意のフォルダ下のテキストファイルをすべて解析して、どの単語が何件ヒットしたかという結果を頻度が多い順に並べて表示させたいです。 やはり、mecabやchasenを利用するべきですか。 ちょっと調べて出てきましたが、R言語とあわせてもう少し自分で調べてみます。 またわからないことがあれば質問させてください。 ご丁寧にありがとうございます。
- ki073
- ベストアンサー率77% (491/634)
日本語ですか、 インターネットのサービスとしては多分存在しないと思います。 コンピュータのソフトはいくつかありますが、それらを組み合わせて使う必要があります。 1)ちょっと確認ですが、「文字」の出現頻度ではなく「単語」ですよねえ。 2)単語の頻度だけが必要なのでしょうか? それとも他の解析をすることを前提としているのでしょうか? 他の解析も考えているのでしたら http://mjin.doshisha.ac.jp/R/ の下の方の「統計的テキスト解析」が参考になります。 単語の頻度でも名詞や動詞限定なのか、助詞や助動詞を含めた全部を数えるのかでも変わってきます。 3)それとMacに入っているターミナルは使ったことがあるでしょうか? プログラミングの知識は必ずしも必要でないですが、ターミナルでコマンドを使う必要がありますので 補足欄にでも書き込んでください。それを見て具体的なやり方を説明します
補足
1) はい、すみません。文字でなく単語です。 2) 哲学書や科学啓蒙書を読んでまとめたメモテキスト(.rtf、.txt)なのですが、人名(「ライプニッツ」や「ガロア」)や専門用語(「モナド」や「群」)等の単語の頻度を調べて、傾向をつかみたいなという程度です。助詞や助動詞まではいりません。どのような単語を使用して思考が組み立てられているかという全体的なパターンを把握したいです。 3) ターミナルの使用は経験があるので大丈夫です。
- ki073
- ベストアンサー率77% (491/634)
ファイルに書かれた言語は何でしょうか。 英語などの空白で単語が分離された言語の場合は比較的簡単に調べられますが、日本語の場合は最初に単語に分解しないと統計をとれませんのでやり方が変わってきます。
補足
日本語です。
お礼
試してみました。 望んだ通りのものです。 ありがとうございます。 基本的なことだと思いますが、もうひとつ質問させてください。 結果をテキストファイルとして出力するにはどのようにすればよいですか? リダイレクトは試しましたが、↓のように表示されました。 $ ruby count_words.rb > out.txt count_words.rb:11:in `abort': can't convert nil into String (TypeError) from count_words.rb:11 from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/open3.rb:86:in `popen3' from count_words.rb:9 from count_words.rb:8:in `each' from count_words.rb:8
補足
すみません、追加で質問です。 ディレクトリが入れ子になっている場合、子ディレクトリ(のさらに子ディレクトリのさらに…)まで対象にするにはどのようにすればよいのでしょうか?