Ruby
形態素解析
natto
Rails5

CSVさえあればいい!形態素解析→単語感情極性対応表で超お手軽ネガポジ分析♪ (with Rails)

More than 1 year has passed since last update.

この記事はフロムスクラッチ Advent Calendar 2016の1日目の記事です。

いえーい!何書いていいかわからなーい!!時間なーい!

よくあるやつでいい!と言われたので、最近やったこと書きます(-人-)

記事の通りにやると!CSVだけあればネガポジ分析結果をRailsで作れます!

コピペで大丈夫です!!

...たぶん動くはず...動作確認甘いかも..その場合コメント下さいませ...絶対なんとかします..


書くこと

先週くらいに社員管理ツールの紹介コンテンツとして、

社員管理ツールから出力したcsvを元にrailsで分析して、

社員ネガポジランキングなるものを発表してみました。

やり方は超単純!なので、プログラム初心者でも

簡単に同じことできるような記事を書いてみます♪

何かに使って頂ければ(ノ・_・)


手順


  • 形態素解析用ライブラリ(natto)を設定する

  • 対象データのcsvと単語感情極性対応表をrailsでDBに簡単に取り込む

  • 形態素解析して点数つけてDBに登録してみる

みたいな感じでやってきます。

処理時間はrubyなのでちょっとかかりますが、

手を動かす時間は少ない!!はず。

rails new hogehogeは省きますのでそこまではやっておいてくださいませ。

ちなみにrails初心者ですので

もしよければ間違いとか改善とかコメント頂ければ嬉しくて涙しますm(_ _)m


解説


形態素解析用ライブラリ(natto)を設定する for Mac


MeCabインストール

※ファイル名がないやつはterminalから実行してください。

※rake 〇〇とかrails 〇〇とかbundle 〇〇は作ったrailsアプリのGemfileとかあるルート階層でお願いします。

brew install mecab

brew install mecab-ipadic

gemにnattoを追加(Gemfileに追記します)


Gemfile

gem 'natto'


gemをインストール

bundle --path vendor/bundler

# bundleだけでもOK


対象データのcsvと単語感情極性対応表をrailsでDBに簡単に取り込む

配置するcsvの一行目はカラム名にして下さいね★

seeds.rbで辞書データと分析対象のデータを取り込みます。

※どんなcsvでもいけるようにするため、かつ、

 最短手数でやるためmodelとか明示的に作らず進めます(*_ _)


seeds.rb

require 'csv'

def download_dic(dic_file_path)
url = 'http://www.lr.pi.titech.ac.jp/~takamura/pubs/pn_ja.dic'
open(url, "r:cp932") do |file|
open(dic_file_path, "w+b") do |out|
# ヘッダだけ追加
out.write('word,word_kana,part_of_speech,score')
out.write(file.read.gsub!(':', ','))
end
end
end

# db/initial_dataには対象のデータのCSVおいておこう
# csvのファイル名は複数形!

csv_file_fir = 'db/initial_data'
# FileUtils.mkdir_p(csv_file_fir) unless File.directory?(csv_file_fir)

# 辞書がなければ取得
dic_file_base_name = 'pn_dics'
dic_file_path = "#{csv_file_fir}/#{dic_file_base_name}.csv"
download_dic(dic_file_path) unless File.exist?(dic_file_path)

connection = ActiveRecord::Base.connection

# initial_data以下のcsv分テーブル作成
Dir.glob("#{csv_file_fir}/*.csv") do |csv|
table_name = File.basename(csv, '.csv')
next if connection.table_exists?(table_name)

target_csv = CSV.table(csv)
# もしカラムを分けたければ1行目を取得して判定など、今回不要
connection.create_table(table_name) do |t|
target_csv.headers.each do |col_name|
# dictのスコアカラムだけfloat
if table_name == dic_file_base_name && col_name == :score
t.float col_name
else
t.string col_name
end
end
# 結果カラムを追加(dictとまとめても良かったけどカラム名分けれるように)
t.float :score if table_name != dic_file_base_name
end

# データを投入(新規テーブルの場合だけ)
class_name = table_name.singularize.camelcase
self.class.const_set class_name, Class.new(ActiveRecord::Base)
klass = table_name.singularize.classify.constantize

target_csv.each do |row|
klass.find_or_create_by!(row.to_hash)
end
end


そして実行!

rake db:seed

長くかかるからログ出した方が楽しいかも(>_<)


形態素解析して点数つけてDBに登録してみる

rakeタスク作って採点→登録をしましょう!

今回はusers.csvをおいておいた想定で、

userにまつわる全文字列情報を形態素解析して、スコアを登録する、

という感じの処理にしておきます。

他のファイルの場合やカラム指定の場合も使いまわせるように書いておきます。

まず、rakeタスク「score_user」を作ります。

rails g task score_user

点数付けのコードを書きます。


lib/tasks/score_user.rake

namespace :score_user do

desc '全ユーザーの点数付け'
task :full_cols => :environment do
# 動的に作っていますが、modelを作成しておいてもOK
self.class.const_set 'User', Class.new(ActiveRecord::Base)
User = 'User'.classify.constantize
self.class.const_set 'PnDic', Class.new(ActiveRecord::Base)
PnDic = 'PnDic'.classify.constantize

User.all.each do |user|
# 全フィールドを結合しています。ここで対象カラムを絞って結合すると良い感じです。
full_text = user.attributes.values.join(",")
require 'natto'

mecab = Natto::MeCab.new
# 形態素解析した文字リストを作ります
list = []
mecab.parse(full_text) do |n|
list.push(n.surface) # if n.feature.match('名詞')
end

score = list.reduce(0.0){|sum, l|
# 点数が付く場合、かつ点数がプラスの時だけを加算していみます
pn = PnDic.find_by(word: l)
sc = pn.score if pn.present? && pn.score > 0
sum + (sc || 0.0)
}
user.score = score # ワードカウントで割り算してもOK -> / list.length
user.save!
end
end
end


taskを実行すると、スコアが付きます!

rake score_user:full_cols

確認してみましょう!

rails db

select * from users;

とか、

rails c

[1] pry(main)> self.class.const_set 'User', Class.new(ActiveRecord::Base)
[2] pry(main)> User = 'User'.classify.constantize
[3] pry(main)> p User.first.score

csvを配置して記事の通りに書くだけで

railsの機能を活用してお手軽にネガポジ分析できました★

ぜひ色々応用してみて下さい。


結論!

めりくりまであと25日!(あってる?)