次に東北大学自然言語処理研究グループによって公開されている日本語評価極性辞書(名詞編)をダウンロードします.このページ (https://www.cl.ecei.tohoku.ac.jp/Open_Resources-Japanese_Sentiment_Polarity_Dictionary.html) から pn.csv.m3.120408.trim というファイルをダウンロードしてください.ダウンロードしたデータは dic
フォルダを作成してその中に格納することにします.なお,この日本語評価極性辞書(名詞編)の参考文献は次の通りです.
dic フォルダに設置した pn.csv.m3.120408.trim ファイルの中身をテキストエディタなどで確認します.文字コードは utf-8 で保存されていることが確認できました.各行には見出し語 (term) と感情 (sentiment) を意味する p, e, n などと,意味カテゴリが記録されています.それぞれがタブ文字で区切られていることにも注意してください.「競争力」や「共感」に与えられている「p」はポジティブな評価極性を意味し,「供給不足」や「魑魅魍魎(ちみもうりょう)」に与えられている「n」はネガティブな評価極性を意味します.「あいさつ」「供給」「競争」などに与えられている「e」はニュートラルな評価極性を意味します.
dic/pn.csv.m3.120408.trim
"2,3日" e 〜である・になる(状態)客観
10% e 〜である・になる(状態)客観
100% e 〜である・になる(状態)客観
25% e 〜である・になる(状態)客観
80% e 〜である・になる(状態)客観
10カ月 e 〜である・になる(状態)客観
10時間 e 〜である・になる(状態)客観
10数年 e 〜である・になる(状態)客観
10年以上 e 〜である・になる(状態)客観
10年近く e 〜である・になる(状態)客観
...(中略)...
1バイト e 〜である・になる(状態)客観
1位 p 〜である・になる(状態)客観
1割 e 〜である・になる(状態)客観
1時間以上 e 〜である・になる(状態)客観
1時間以内 e 〜である・になる(状態)客観
1時間半 e 〜である・になる(状態)客観
...(中略)...
AD e 〜である・になる(状態)客観
AIDS n 〜である・になる(状態)客観
ATフィールド p 〜がある・高まる(存在・性質)
Amazon e 〜である・になる(状態)客観
A型肝炎 n 〜である・になる(状態)客観
BBC e 〜である・になる(状態)客観
...(中略)...
あいさつ e 〜する(行為)
あいだ e 〜である・になる(状態)客観
あいつら e 〜である・になる(状態)客観
あいまい n 〜である・になる(評価・感情)主観
...(中略)...
供給 e 〜する(行為)
供給不足 n 〜である・になる(状態)客観
供与 e 〜する(行為)
供養 e 〜する(行為)
侠盗 e 〜である・になる(評価・感情)主観
競り合い e 〜がある・高まる(存在・性質)
競合 e 〜する(行為)
競作 e 〜する(行為)
競争心 e 〜がある・高まる(存在・性質)
競争相手 e 〜がある・高まる(存在・性質)
競争率 e 〜がある・高まる(存在・性質)
競争力 p 〜がある・高まる(存在・性質)
共感 p 〜する(出来事)
共存 e 〜する(出来事)
...(中略)...
魑魅魍魎 n 〜である・になる(状態)客観
鮑 e 〜である・になる(状態)客観
鹹味 e 〜である・になる(評価・感情)主観
麒麟 e 〜である・になる(状態)客観
形態素解析を行なって単語に分割した後,上の日本語評価極性辞書からその評価極性を取得することで感情分析ができそうです.実際に感情分析を行う前にこの辞書データを読み込んでその内容を確認してみます.dic フォルダに格納した pn.csv.m3.120408.trim を Python の Pandas で読み込みます.このとき,文字コードが utf-8 であること,カンマ (,) ではなくタブ文字で区切られていることに注意します.また,見出し行がないことから列名も指定します.
import pandas as pd
import os
# 日本語評価極性辞書(名詞編)
path_dic = os.path.sep.join(['dic', 'pn.csv.m3.120408.trim'])
df_pncsv = pd.read_csv(path_dic, sep="\t", names=["term", "sentiment", "semantic_category"])
df_pncsv
上の結果から,13,314個の見出し語 (term) が登録されていることがわかりました.また,感情 (sentiment) には p, n, e などの存在が確認できました.どのような割合で感情が登録されているかを次のコードで確認します.すると,p, n, e が大半を占めますが,それら以外にも存在することがわかりました.
どのような感情がどのような割合で登録されているか?
df_sentiment = df_pncsv.groupby('sentiment')['term'].count().reset_index()
df_sentiment = df_sentiment.sort_values(by=['term'], ascending=[False])
df_sentiment
まず,ポジティブ (p) の感情を持つ見出し語がどのようなものであるかを確認します.
df_pncsv[df_pncsv.sentiment=="p"]
感情がニュートラル (e) である見出し語を確認します.
df_pncsv[df_pncsv.sentiment=="e"]
次はネガティブ (n) な感情を持つ見出し語を確認します.
df_pncsv[df_pncsv.sentiment=="n"]
感情には「?p?n」なるものがありました.どのような見出し語に「?p?n」が割り当てられているか表示してみます.これらはポジティブであるかネガティブであるか曖昧であるが,そのどちらかであると推定できそうです.
print(df_pncsv[df_pncsv.sentiment=="?p?n"])
term sentiment semantic_category 431 ぐうたら ?p?n 〜する(行為) 452 こだわり ?p?n 〜がある・高まる(存在・性質) 778 ぶらぶら ?p?n 〜する(行為) 971 アピール ?p?n 〜する(行為) 1740 ナンパ ?p?n 〜する(行為) 1797 ハプニング ?p?n 〜がある・高まる(存在・性質) 2232 リタイア ?p?n 〜する(行為) 2330 哀愁 ?p?n 〜がある・高まる(存在・性質) 2778 迂回 ?p?n 〜する(行為) 2836 永眠 ?p?n 〜する(出来事) 3362 海賊 ?p?n 〜である・になる(状態)客観 3664 甘さ ?p?n 〜がある・高まる(存在・性質) 3733 関わり ?p?n 〜がある・高まる(存在・性質) 3871 機嫌 ?p?n 〜である・になる(状態)客観 3888 気 ?p?n 〜がある・高まる(存在・性質) 4277 強気 ?p?n 〜である・になる(評価・感情)主観 4411 均衡 ?p?n 〜する(出来事) 4504 苦心 ?p?n 〜する(出来事) 5270 公表 ?p?n 〜する(行為) 5526 高値 ?p?n 〜である・になる(状態)客観 6416 自慢 ?p?n 〜する(行為) 6696 手術 ?p?n 〜する(行為) 7640 深さ ?p?n 〜がある・高まる(存在・性質) 7986 凄さ ?p?n 〜がある・高まる(存在・性質) 8269 静か ?p?n 〜である・になる(評価・感情)主観 9314 値下がり ?p?n 〜する(出来事) 9318 値上がり ?p?n 〜する(出来事) 10062 頭 ?p?n 〜である・になる(状態)客観 & ?〜である・になる(状態)客観 10118 道草 ?p?n 〜する(行為) 10456 濃厚 ?p?n 〜である・になる(評価・感情)主観 11016 必要性 ?p?n 〜がある・高まる(存在・性質) 11115 敏感 ?p?n 〜である・になる(状態)客観 & ?〜である・になる(状態)主観 11645 変貌 ?p?n 〜する(出来事) 11685 弁償 ?p?n 〜する(行為) 12007 満席 ?p?n 〜である・になる(状態)客観
その他の感情が与えられた見出しををまとめて表示してみます.「?e」はニュートラルであると推定され,「?p」はポジティブであると推定され,「?p?e」はポジティブかニュートラルかが曖昧な見出し語です.さらに「a:ambiguous」は曖昧な見出し語,「o:other」はその他を意味しますが,「決壊」については全角空白で感情が割り当てられています.
df_pncsv[(df_pncsv.sentiment!="p") &
(df_pncsv.sentiment!="e") &
(df_pncsv.sentiment!="n") &
(df_pncsv.sentiment!="n") &
(df_pncsv.sentiment!="?p?n")
].sort_values('sentiment')
次に意味カテゴリについてもどのような情報が登録されているかグループ化して表示してみます.多くの意味カテゴリに分類されているようですが,今回はこれらの情報は利用しないことにします.
df_cat = df_pncsv.groupby('semantic_category')['term'].count().reset_index()
df_cat = df_cat.sort_values(by=['term'], ascending=[False])
print(df_cat)
semantic_category term 1 〜がある・高まる(存在・性質) 4354 33 〜である・になる(状態)客観 2940 14 〜する(行為) 2369 40 〜である・になる(評価・感情)主観 2303 8 〜する(出来事) 978 48 〜に行く(場所) 142 28 〜する(行為)他人 73 29 〜する(行為)自分 62 27 〜する(行為)その他 17 6 〜する(出来事) 8 17 〜する(行為) & !〜する(出来事)もあり 6 20 〜する(行為) & ?〜する(出来事)もあり? 4 50 存在・もの・名称 4 19 〜する(行為) & ?〜する(出来事) 3 2 〜がある・高まる(存在・性質) & !〜する(行為)もあり 3 49 和語動詞 3 34 〜である・になる(状態)客観 & !〜がある・高まる(存在・性質)もあり 2 15 〜する(行為) & !〜がある・高まる(存在・性質)もあり 2 43 〜である・になる(評価・感情)主観 & !〜である・になる(評価・感情)客観もあり 2 44 〜である・になる(評価・感情)主観 & !〜である・になる(評価・感情)客観もあり? 2 39 〜である・になる(状態)客観 & ?〜である・になる(状態)客観 2 23 〜する(行為) & ?〜する(出来事) 2 24 〜する(行為) & ?〜する(出来事)もあり? 2 36 〜である・になる(状態)客観 & !〜をする(出来事)もあり 1 35 〜である・になる(状態)客観 & !〜がある・高まる(存在・性質)もあり? 1 47 〜である・になる(評価・感情)主観 & 〜である・になる(評価・感情)客観もあり 1 41 〜である・になる(評価・感情)主観 & !〜がある・高まる(存在・性質)もあり 1 46 〜である・になる(評価・感情)主観 & ?〜である・になる(評価・感情)客観もあり? 1 42 〜である・になる(評価・感情)主観 & !〜する(行為)もあり 1 38 〜である・になる(状態)客観 & ?〜である・になる(状態)主観 1 45 〜である・になる(評価・感情)主観 & ?〜する(行為)もあり? 1 37 〜である・になる(状態)客観 & ?〜する(出来事)もあり? 1 0 〜である・になる(状態)客観 1 32 〜する(行為)自分 & ?〜する(出来事) 1 31 〜する(行為)自分 & !〜する(出来事)? 1 3 〜がある・高まる(存在・性質) & !〜である・になる(状態)主観もあり 1 4 〜がある・高まる(存在・性質) & !〜である・になる(状態)客観もあり 1 5 〜がある・高まる(存在・性質) & 〜である・になる(評価・感情)主観もあり 1 7 〜する(行為) 1 9 〜する(出来事) & !〜がある・高まる(存在・性質)もあり 1 10 〜する(出来事) & !〜する(行為)もあり 1 11 〜する(出来事) & !〜である・になる(状態)客観もあり 1 12 〜する(出来事) & ?〜する(行為) 1 13 〜する(出来事) & 〜がある・高まる(存在・性質)客観もあり 1 16 〜する(行為) & !〜する(出来事)? 1 18 〜する(行為) & !〜する(行為)もあり 1 21 〜する(行為) & ?〜する(出来事) 1 22 〜する(行為) & ?〜する(行為)もあり? 1 26 〜する(行為) & 〜である・になる(評価・感情)客観もあり 1 30 〜する(行為)自分 & !〜がある・高まる(存在・性質)もあり 1 25 〜する(行為) & ?〜する(行為) 1
すでに13,314個の見出し語が登録されていることは確認しましたが,これらの見出し語に重複があるかどうかをここで確認しておきます.まず,データフレームから見出し語の列を抽出,さらにリスト化して,その個数を調べると同じ13,314が得られるはずです.
term = df_pncsv["term"].tolist()
print(len(term))
13314
リストから集合を作成すると重複を除くことができます.重複を除くと 13,310件に減少しました.
term_set = set(term)
print(len(term_set))
13310
(暗算で可能ですが)重複した見出し語の個数をカウントします.
print(len(term) - len(term_set))
4
4個の見出し語については重複があるようです.重複があった用語を表示します.
sorted_df = df_pncsv.groupby('term')['sentiment'].count().reset_index()
sorted_df = sorted_df.sort_values(by=['sentiment'], ascending=[False])
sorted_df[sorted_df.sentiment > 1]
これらの重複があった用語にはどのような感情が割り当てられているのでしょうか.そのことを確認します.「信用」と「帳消し」についてはいずれも「p」です.「規律」については「e」または「p」,「白濁」は「a」または「e」です.よって「規律」と「白濁」の取り扱いをどうするかは必要に応じて検討しましょう.今回は無視することにします.
df_pncsv[(df_pncsv.term == "帳消し") |
(df_pncsv.term == "信用") |
(df_pncsv.term == "規律") |
(df_pncsv.term == "白濁")
]
さらに,今回利用する日本語評価極性辞書(名詞編)において,数字やアルファベットを含む見出し語はその殆どが全角文字で登録されています.一方で,前のページで確認した通り MeCab で形態素解析を実行する場合は事前に半角文字に変換(正規化)することで解析の精度が向上します.したがって,日本語評価極性辞書の見出し語をあらかじめ正規化して半角文字に変換しておきます.
まず,見出し語の列だけ取り出してリスト化します.そのうえで先頭150個を3個おきに表示します.個の結果の('25%'を除く)ほぼすべてが全角文字であることに注意してください.
term = df_pncsv['term'].tolist()
print(term[:150:3])
['2,3日', '25%', '10時間', '10年近く', '12年', '15秒', '19年', '1割', '1時間半', '1勝', '1日分', '1品', '20年近く', '2ヵ月', '2件目', '2時間半', '2勝1敗', '2年近く', '30分程度', '39歳', '3タテ', '3回連続', '3酔い', '4か月', '4日', '50年以上', '7ヶ月', '8カ月', '9ヶ月', 'AD', 'Amazon', 'BIG', 'CD', 'DV', 'ED', 'HIV', 'HTML', 'KO', 'OK', 'PMS', 'Q&A', 'RSS', 'SPAM', 'TKO', 'Web検索', 'end', 'txt', 'あいつら', 'あえぎ', 'あきらめ']
ここで説明した方法を使って正規化します.このとき内包表記を使うことでコードが短くなるとともに実行速度の向上も期待できます.半角文字に正規化できていることがわかりました.
import unicodedata
term_nfkc = [unicodedata.normalize('NFKC', t) for t in term] # 内包表記を使って半角文字に正規化する
print(term_nfkc[:150:3])
['2,3日', '25%', '10時間', '10年近く', '12年', '15秒', '19年', '1割', '1時間半', '1勝', '1日分', '1品', '20年近く', '2ヵ月', '2件目', '2時間半', '2勝1敗', '2年近く', '30分程度', '39歳', '3タテ', '3回連続', '3酔い', '4か月', '4日', '50年以上', '7ヶ月', '8カ月', '9ヶ月', 'AD', 'Amazon', 'BIG', 'CD', 'DV', 'ED', 'HIV', 'HTML', 'KO', 'OK', 'PMS', 'Q&A', 'RSS', 'SPAM', 'TKO', 'Web検索', 'end', 'txt', 'あいつら', 'あえぎ', 'あきらめ']
データフレームでの見出し語の列を正規化した内容に置き換えます.
df_pncsv['term'] = term_nfkc
df_pncsv