自分用メモ。
単語のポジネガをぱっと見で確認するのに結果を色付きで見れると便利。Rubyでそういうgemを作っている人がいたので使わせてもらう。
require "colored" puts "this is red".red
とかやるとターミナルに赤く表示される。が、色々色があるときにcaseで分けてやるとか面倒なので、"red"とかのmethodを呼び出すのを動的にしたい。結論からいうとKernel#sendを使うとうまく扱うことができる(すぐに忘れる)。
実際の例。例えばこんなファイルから色を付けたい。
% cat data/WordLevel_10.txt Document-Level Polarity: 0.512755, 0.487245 0.833333, 0, 0.166667: ,(0.5, 0, 0.5) sorry(1, 0, 0) bill(1, 0, 0) 0.423077, 0.461538, 0.115385: this(0.5, 0.5, 0) and(0.5, 0, 0.5) have(0.5, 0.5, 0) a(0, 0.5, 0.5) only(1, 0, 0) made(0, 1, 0) most(0.5, 0.5, 0) purchase(0, 0.5, 0.5) poor(0.5, 0.5, 0) fair(0.5, 0.5, 0) production(0.5, 0.5, 0) disappointing(0, 1, 0) lyrics(1, 0, 0) 0.346154, 0.423077, 0.230769: this(0.5, 0.5, 0) to(0, 0.5, 0.5) the(0, 1, 0) is(0.5, 0.5, 0) ,(0.5, 0.5, 0) but(0.5, 0, 0.5) enough(0.5, 0, 0.5) material(0, 0.5, 0.5) save(0, 1, 0) adequate(0, 0.5, 0.5) playing(1, 0, 0) guitar(0.5, 0.5, 0) not_good(0.5, 0, 0.5) 0.111111, 0.666667, 0.222222: the(0, 0.5, 0.5) i(0, 1, 0) a(0, 0.5, 0.5) thought(0.5, 0.5, 0) on(0, 0, 1) more(0.5, 0.5, 0) out(0, 1, 0) little(0, 0, 1) time(0, 1, 0) before(0, 1, 0) material(0, 1, 0) his(0, 1, 0) bill(0.5, 0, 0.5) next(0, 1, 0) hope(0, 1, 0) process(0, 1, 0) bringing(0.5, 0, 0.5) spends(0, 1, 0)
で、こんなスクリプトをでっちあげる。
require "colored" # RubyにはRでいうところのwhich.minみたいな関数はないんでしたっけ...? class Array def max_index max_index = 0 max = - 1.0/0 self.each_with_index{|elem, index| if elem > max max = elem max_index = index end } return max_index end end polarity2color = Hash.new polarity2color[0] = "blue" polarity2color[1] = "red" polarity2color[2] = "green" if ARGV.size != 1 puts "usage; ruby #{__FILE__} filename" exit end filename = ARGV[0] if !File.exist?(filename) STDERR.puts "#{filename} doesn't exist!" exit end File.open(filename, "r") {|file| skip_num = file.gets.split("\s").last.to_i skip_num.times do file.gets end file.each{|line| line.chomp! if line =~ /(\d*.\d*), (\d*.\d+), (\d*.\d+): (.*)/ sentence_pos_prob = $1; sentence_neg_prob = $2; sentence_neu_prob = $3; rest = $4 sentence_pos_prob = sentence_pos_prob.to_f; sentence_neg_prob = sentence_neg_prob.to_f; sentence_neu_prob = sentence_neu_prob.to_f sentence_prob = [sentence_pos_prob, sentence_neg_prob, sentence_neu_prob] max_index = sentence_prob.max_index print "#{sentence_prob[max_index].to_s.send(polarity2color[max_index]).send(:underline)} " rest.scan(/(.*?)\((\d*.\d*), (\d*.\d*), (\d*.\d*)\) /).each{|chunk| word, word_pos_prob, word_neg_prob, word_neu_prob = chunk word_pos_prob = word_pos_prob.to_f; word_neg_prob = word_neg_prob.to_f; word_neu_prob = word_neu_prob.to_f word_prob = [word_pos_prob, word_neg_prob, word_neu_prob] print "#{word.send(polarity2color[word_prob.max_index])} " } puts end } }
すると、こんな感じの出力を得ることができる。ターミナルの上で見れるので(自分にとって)便利。
sendとかの分かりやすい例はRubyベストプラクティス -プロフェッショナルによるコードとテクニックのp75とかに載っていた。