この記事はフロムスクラッチ 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に追記します)
gem 'natto'
gemをインストール
bundle --path vendor/bundler
# bundleだけでもOK
対象データのcsvと単語感情極性対応表をrailsでDBに簡単に取り込む
配置するcsvの一行目はカラム名にして下さいね★
seeds.rbで辞書データと分析対象のデータを取り込みます。
※どんなcsvでもいけるようにするため、かつ、
最短手数でやるためmodelとか明示的に作らず進めます(*_ _)
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
点数付けのコードを書きます。
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日!(あってる?)