次に,東京工業大学の奥村・船越研究室 (https://lr-www.pi.titech.ac.jp/wp/) で公開されている単語感情極性対応表をダウンロードします.このページ (http://www.lr.pi.titech.ac.jp/~takamura/pndic_ja.html) から日本語の辞書データ (pn_ja.dic) をダウンロードしてください.ダウンロードしたデータは dic
フォルダを作成してその中に格納することにします.なお,この単語感情極性対応表の参考文献は次の通りです.
dic フォルダに設置した pn_ja.dic ファイルの中身をテキストエディタなどで確認します.文字コードが utf-8 ではなく Shift-JIS になっていることに注意してください.各行には「見出し語」「読み」「品詞」「感情極性実数値」が記録されており,それぞれがコロン「:」で区切られています.さらに,感情極性実数値は+1から-1までの値になっていることがわかります.「優れる」や「良い」という見出し語は良い印象を持つ positive な単語であり,「死ぬ」や「悪い」という見出し語は悪い印象を持つ negative な単語であると言えます.
dic/pn_ja.dic
優れる:すぐれる:動詞:1
良い:よい:形容詞:0.999995
喜ぶ:よろこぶ:動詞:0.999979
褒める:ほめる:動詞:0.999979
めでたい:めでたい:形容詞:0.999645
賢い:かしこい:形容詞:0.999486
...(中略)...
大尉:たいい:名詞:0.000344221
婦徳:ふとく:名詞:0.000205878
用務:ようむ:名詞:0.00012227
救貧:きゅうひん:名詞:3.01237e-05
漏斗:ろうと:名詞:0
夜曲:やきょく:名詞:0
冬籠る:ふゆごもる:動詞:0
沢庵:たくわん:名詞:0
他称:たしょう:名詞:0
第三人称:だいさんにんしょう:名詞:0
セレナーデ:セレナーデ:名詞:0
巨体:きょたい:名詞:0
巨躯:きょく:名詞:0
細螺:きしゃご:名詞:0
忌明け:きあけ:名詞:0
ウイーク エンド:ウイーク エンド:名詞:0
温突:オンドル:名詞:0
州浜:すわま:名詞:0
眇める:すがめる:動詞:0
眇む:すがむ:動詞:0
白子:しろこ:名詞:0
週末:しゅうまつ:名詞:0
小夜曲:さよきょく:名詞:0
啄木鳥:けらつつき:名詞:0
新設:しんせつ:名詞:-4.80247e-05
公方:くぼう:名詞:-8.89323e-05
銃傷:じゅうしょう:名詞:-0.000100071
お母さん:おかあさん:名詞:-0.000145459
ちえ袋:ちえぶくろ:名詞:-0.00015696
...(中略)...
ない:ない:形容詞:-0.999882
浸ける:つける:動詞:-0.999947
罵る:ののしる:動詞:-0.999961
ない:ない:助動詞:-0.999997
酷い:ひどい:形容詞:-0.999997
病気:びょうき:名詞:-0.999998
死ぬ:しぬ:動詞:-0.999999
悪い:わるい:形容詞:-1
Python の pandas でこのファイルを読み込んでみましょう.文字コードが sjis であること,カンマ (,) ではなくコロン (:) で区切られていることに注意します.また,見出し行がないことから列名も指定します.
import pandas as pd
import os
# 単語感情極性対応表
path_dic = os.path.sep.join(['dic', 'pn_ja.dic'])
df_pn = pd.read_csv(path_dic, encoding="sjis", sep=":", names=["lemma", "reading", "pos", "score"])
df_pn
上の出力結果から 55,125件の見出し語が登録されていることがわかります.データフレームから見出し語の列を抽出,さらにリスト化して,その個数を調べます.
見出し語(原型:lemma)が何個あるか
lemma = df_pn["lemma"].tolist()
print(len(lemma))
55125
リストから集合を作成すると重複を除くことができます.重複を除くと 52,671件に減少しました.
集合を作成して重複を除く
lemma_set = set(lemma)
print(len(lemma_set))
52671
重複した見出し語の個数をカウントします.
重複の個数
print(len(lemma) - len(lemma_set))
2454
2,454件の重複が確認できました.どのような見出し語に重複があるのかを確認します.このためには Pandas の groupby を用いて見出し語 (lemma) でグループ化し,その個数をカウントします.
sorted_df = df_pn.groupby('lemma')['score'].count().reset_index()
sorted_df = sorted_df.sort_values(by=['score'], ascending=[False])
sorted_df[sorted_df.score > 1]
2,050個の見出し語については重複して登録されていることがわかります.たとえば見出し語「ホーム」には11個の感情極性実数値が登録されているわけです.この詳細は確認してくべきでしょう.データフレームから lamma に "ホーム" と登録された行をすべて抽出します.すると,読みの「ホームラン」,「ホームスパン」,「ホーム」などがすべて見出し語「ホーム」として登録されていることがわかりました.これらの取り扱いをどうするかは後ほど検討することにします.
df_pn[df_pn.lemma == "ホーム"]
「ホームラン」の「ラン」や「ホームスパン」の「スパン」は登録されていませんが,「ホームドラマ」の「ドラマ」や「ホームヘルパー」の「ヘルパー」は個別に登録されていることも確認できます.
print(df_pn[df_pn.lemma == "ラン"])
Empty DataFrame Columns: [lemma, reading, pos, score] Index: []
print(df_pn[df_pn.lemma == "スパン"])
Empty DataFrame Columns: [lemma, reading, pos, score] Index: []
print(df_pn[df_pn.lemma == "ドラマ"])
lemma reading pos score 14874 ドラマ ドラマ 名詞 -0.188471
print(df_pn[df_pn.lemma == "ヘルパー"])
lemma reading pos score 20616 ヘルパー ヘルパー 名詞 -0.25243
さらに,重複のあった「大和」,「太刀」,「頭」,「猿」についてもどのような重複データとして登録されているか確認します.また,「ホームラン」の読みはカタカナで登録されていますが,「やまとなでしこ」の読みはひらがなで登録されていることにも注意してください.
df_pn[df_pn.lemma == "大和"]
df_pn[df_pn.lemma == "太刀"]
df_pn[df_pn.lemma == "頭"]
df_pn[df_pn.lemma == "猿"]
さらに,どのような品詞が登録されているかを確認します.すると圧倒的に名詞が多く登録されていることがわかりました.
df_pn.groupby('pos')['score'].count()
pos 副詞 1207 助動詞 2 動詞 4252 名詞 48999 形容詞 665 Name: score, dtype: int64
続いて,感情極性実数値の平均値など基本統計量を確認します.これは Pandas の describe() を使うと良いでしょう.この結果,感情極性実数値の平均値がゼロではなくおよそ -0.32 であること,多くの見出し語の感情極性実数値は負の値になっていることに注意してください.
df_pn['score'].describe()
count 55125.000000 mean -0.319764 std 0.382738 min -1.000000 25% -0.522353 50% -0.339964 75% -0.176277 max 1.000000 Name: score, dtype: float64
感情極性実数値がどのような分布になっているかも確認しておくべきでしょう.これは ydata-profiling でレポートを作成すると簡単に確認できます.
ydata-profiling でレポートを作成
from ydata_profiling import ProfileReport
profile = ProfileReport(df_pn)
profile.to_file("pn_report.html")
カレントフォルダに pn_report.html というファイルが出力されているはずなので,その中身を確認するとよいでしょう.この結果,全体の 90.7% もが負の値になっていることがわかります.さらに次のヒストグラムからは,-0.9から-0.5の範囲に多くのデータがある一方で,+0.5から+0.9の範囲にはほとんど存在しないこともわかります.これら結果からわかることは,感情極性実数値が正である見出し語が圧倒的に少ない(およそ9.3%である)ことから,正か負かという情報だけで positive/negative の判定をすると多くの場合で negative という結果になってしまうということです.
続いて,見出し語から感情極性実数値が得られるように辞書を作成します.ただし,現段階では「ホーム」や「大和」など重複のある見出し語についての処理には潜在的な問題があることにも注意してください.重複を無視すれば次の方法で簡単にデータフレームから辞書を作成することができます.
辞書の作成
dic_lemma = df_pn.set_index('lemma')['score'].to_dict()
作成した辞書を表示してみます.(ただし,非常に多くの結果が表示されるので実行には注意してください.)
print(dic_lemma)
{'優れる': 1.0, '良い': 0.999995, '喜ぶ': 0.999979, ...(中略)... 'ホーム': -0.408128, ...(中略)... '大和': -0.571956, ...(中略)... '病気': -0.999998, '死ぬ': -0.999999, '悪い': -1.0}
上の辞書 dic_lemma
から「ホーム」の値だけを抽出します.
dic_lemma['ホーム']
-0.408128
データフレームから見出し語「ホーム」の行をすべて抽出します.辞書 dic_lemma
に「ホーム」として格納されている値は最後の「ホームヘルパー」の値 -0.408128 だけであることに注意してください(この問題は次のページ以降で処理します).
df_pn[df_pn.lemma == "ホーム"]
さらに理解を深めるために,読みでもグループ化してどの程度の重複があるかを確認しておきます.読みでは 6,063件の重複があり,中でも「しょう」という読みでは45件の見出し語が登録されていることがわかります.
sorted_df = df_pn.groupby('reading')['score'].count().reset_index()
sorted_df = sorted_df.sort_values(by=['score'], ascending=[False])
print(sorted_df[sorted_df.score > 1])
reading score 15391 しょう 45 13840 し 40 6499 かん 37 7171 き 34 19384 そう 33 ... ... ... 2079 いへん 2 34097 みけん 2 22207 ちょうあい 2 10206 けっき 2 15483 しょうしゅつ 2 [6063 rows x 2 columns]
「しょう」という読みでどのような見出し語が登録されているか確認します.
print(df_pn[df_pn.reading == "しょう"])
lemma reading pos score 11 賞 しょう 名詞 0.998943 115 昌 しょう 名詞 0.996219 509 正 しょう 名詞 0.990394 767 奨 しょう 名詞 0.987421 993 勝 しょう 名詞 0.983870 1438 祥 しょう 名詞 0.975947 1907 笑 しょう 名詞 0.963530 2088 匠 しょう 名詞 0.953358 3080 捷 しょう 名詞 0.264843 5625 性 しょう 名詞 -0.026737 7477 沼 しょう 名詞 -0.087891 14807 廠 しょう 名詞 -0.187703 16261 庄 しょう 名詞 -0.203384 16642 晶 しょう 名詞 -0.207766 17346 松 しょう 名詞 -0.215653 18159 照 しょう 名詞 -0.224491 21181 将 しょう 名詞 -0.258830 22097 背負う しょう 動詞 -0.270019 22110 昭 しょう 名詞 -0.270113 25526 宵 しょう 名詞 -0.312423 26771 升 しょう 名詞 -0.329012 27777 省 しょう 名詞 -0.342514 29073 渉 しょう 名詞 -0.360132 31167 商 しょう 名詞 -0.388045 31946 荘 しょう 名詞 -0.397786 34975 尚 しょう 名詞 -0.435942 36396 詔 しょう 名詞 -0.453293 37903 笙 しょう 名詞 -0.473510 37920 象 しょう 名詞 -0.473671 40299 彰 しょう 名詞 -0.506979 41250 証 しょう 名詞 -0.521029 42343 小 しょう 名詞 -0.538430 42501 昇 しょう 名詞 -0.540795 42978 醤 しょう 名詞 -0.548599 45147 装 しょう 名詞 -0.588353 45567 章 しょう 名詞 -0.596776 46178 床 しょう 名詞 -0.609430 47049 称 しょう 名詞 -0.630153 48521 掌 しょう 名詞 -0.676449 48659 妾 しょう 名詞 -0.681568 49666 鉦 しょう 名詞 -0.725421 50529 焼 しょう 名詞 -0.780068 51106 鐘 しょう 名詞 -0.825152 52845 症 しょう 名詞 -0.985740 55014 傷 しょう 名詞 -0.998220
重複の多かった「そう」についても同様に確認しておきましょう.
print(df_pn[df_pn.reading == "そう"])
lemma reading pos score 402 聡 そう 名詞 0.991917 480 壮 そう 名詞 0.990775 9216 早 そう 名詞 -0.119214 12524 艘 そう 名詞 -0.161492 17818 操 そう 名詞 -0.220665 26017 宋 そう 名詞 -0.318915 29367 蒼 そう 名詞 -0.364092 31913 双 そう 名詞 -0.397465 32276 槍 そう 名詞 -0.402230 32482 宗 そう 名詞 -0.405082 32873 相 そう 名詞 -0.410390 33561 槽 そう 名詞 -0.418203 33679 桑 そう 名詞 -0.419539 34658 奏 そう 名詞 -0.432226 40388 叢 そう 名詞 -0.508289 41026 瘡 そう 名詞 -0.517506 41151 想 そう 名詞 -0.519655 41224 窓 そう 名詞 -0.520621 41367 創 そう 名詞 -0.522894 41786 倉 そう 名詞 -0.529372 42228 藻 そう 名詞 -0.536728 42549 荘 そう 名詞 -0.541712 44463 箏 そう 名詞 -0.575231 46611 装 そう 名詞 -0.619199 47252 相 そう 名詞 -0.636353 47409 喪 そう 名詞 -0.640564 48157 葬 そう 名詞 -0.663802 48912 層 そう 名詞 -0.690597 50158 霜 そう 名詞 -0.754495 50647 沿う そう 動詞 -0.789147 50918 巣 そう 名詞 -0.810283 51329 僧 そう 名詞 -0.847341 51940 草 そう 名詞 -0.946003