日本語の文章から感情分析を行うためには,まず文章を単語(厳密には形態素)に分割する作業,つまり形態素解析が必要です.ここでは,MeCab を利用して形態素解析を行うことにします.あらかじめ,このページを参照して MeCab を利用できるようにしてください.なお,この「日本語評価極性辞書(名詞編)を用いた感情分析」では,macOS を用いて mecab-ipadic-NEologd 辞書で形態素解析を実行することを前提に進めます.Windows を利用した場合や,他の辞書を利用した場合には結果が一部異なりますが,感情分析を行うこと自体は可能です.
MeCab のインストールができたら Python で形態素解析を実行します.ここでは「今日の勝利で1位に躍進して優勝が濃厚になったことが競争相手にとっては痛手となった」という文について形態素解析を実行してみます.なお,「1位」の「1」には全角文字を利用していることに注意してください.
import MeCab as mc
import unicodedata
# t = mc.Tagger() # for Windows
# t = mc.Tagger('-r /dev/null -d /opt/homebrew/lib/mecab/dic/ipadic') # for macOS
t = mc.Tagger('-r /dev/null -d /opt/homebrew/lib/mecab/dic/mecab-ipadic-neologd') # for macOS
sent = "今日の勝利で1位に躍進して優勝が濃厚になったことが競争相手にとっては痛手となった"
print(t.parse(sent))
今日 名詞,副詞可能,*,*,*,*,今日,キョウ,キョー
の 助詞,連体化,*,*,*,*,の,ノ,ノ
勝利 名詞,サ変接続,*,*,*,*,勝利,ショウリ,ショーリ
で 助詞,格助詞,一般,*,*,*,で,デ,デ
1 名詞,数,*,*,*,*,1,イチ,イチ
位 名詞,接尾,助数詞,*,*,*,位,イ,イ
に 助詞,格助詞,一般,*,*,*,に,ニ,ニ
躍進 名詞,サ変接続,*,*,*,*,躍進,ヤクシン,ヤクシン
し 動詞,自立,*,*,サ変・スル,連用形,する,シ,シ
て 助詞,接続助詞,*,*,*,*,て,テ,テ
優勝 名詞,サ変接続,*,*,*,*,優勝,ユウショウ,ユーショー
が 助詞,格助詞,一般,*,*,*,が,ガ,ガ
濃厚 名詞,形容動詞語幹,*,*,*,*,濃厚,ノウコウ,ノーコー
に 助詞,格助詞,一般,*,*,*,に,ニ,ニ
なっ 動詞,自立,*,*,五段・ラ行,連用タ接続,なる,ナッ,ナッ
た 助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
こと 名詞,非自立,一般,*,*,*,こと,コト,コト
が 助詞,格助詞,一般,*,*,*,が,ガ,ガ
競争相手 名詞,固有名詞,一般,*,*,*,競争相手,キョウソウアイテ,キョーソーアイテ
にとって 助詞,格助詞,連語,*,*,*,にとって,ニトッテ,ニトッテ
は 助詞,係助詞,*,*,*,*,は,ハ,ワ
痛手 名詞,一般,*,*,*,*,痛手,イタデ,イタデ
と 助詞,格助詞,一般,*,*,*,と,ト,ト
なっ 動詞,自立,*,*,五段・ラ行,連用タ接続,なる,ナッ,ナッ
た 助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
EOS
上の結果では「1位」が「1」と「位」という形態素に分割されてしまいました.あらかじめ「1位」を半角文字である「1位」に正規化してから形態素解析を実行します.なお,正規化の詳細はこちらを参照してください.これによって「1位」という形態素として認識できました.
t = mc.Tagger('-r /dev/null -d /opt/homebrew/lib/mecab/dic/mecab-ipadic-neologd') # for macOS
sent = "今日の勝利で1位に躍進して優勝が濃厚になったことが競争相手にとっては痛手となった"
print(t.parse(unicodedata.normalize('NFKC', sent)))
今日 名詞,副詞可能,*,*,*,*,今日,キョウ,キョー の 助詞,連体化,*,*,*,*,の,ノ,ノ 勝利 名詞,サ変接続,*,*,*,*,勝利,ショウリ,ショーリ で 助詞,格助詞,一般,*,*,*,で,デ,デ 1位 名詞,固有名詞,一般,*,*,*,1位,イチイ,イチー に 助詞,格助詞,一般,*,*,*,に,ニ,ニ 躍進 名詞,サ変接続,*,*,*,*,躍進,ヤクシン,ヤクシン し 動詞,自立,*,*,サ変・スル,連用形,する,シ,シ て 助詞,接続助詞,*,*,*,*,て,テ,テ 優勝 名詞,サ変接続,*,*,*,*,優勝,ユウショウ,ユーショー が 助詞,格助詞,一般,*,*,*,が,ガ,ガ 濃厚 名詞,形容動詞語幹,*,*,*,*,濃厚,ノウコウ,ノーコー に 助詞,格助詞,一般,*,*,*,に,ニ,ニ なっ 動詞,自立,*,*,五段・ラ行,連用タ接続,なる,ナッ,ナッ た 助動詞,*,*,*,特殊・タ,基本形,た,タ,タ こと 名詞,非自立,一般,*,*,*,こと,コト,コト が 助詞,格助詞,一般,*,*,*,が,ガ,ガ 競争相手 名詞,固有名詞,一般,*,*,*,競争相手,キョウソウアイテ,キョーソーアイテ にとって 助詞,格助詞,連語,*,*,*,にとって,ニトッテ,ニトッテ は 助詞,係助詞,*,*,*,*,は,ハ,ワ 痛手 名詞,一般,*,*,*,*,痛手,イタデ,イタデ と 助詞,格助詞,一般,*,*,*,と,ト,ト なっ 動詞,自立,*,*,五段・ラ行,連用タ接続,なる,ナッ,ナッ た 助動詞,*,*,*,特殊・タ,基本形,た,タ,タ EOS
なお,Windows を利用している場合や macOS であっても IPA 辞書を利用している場合には「1位」のように正規化をしていても形態素解析の結果では分割されてしまいます.また,「競争」と「相手」が2つの単語として分割されてしまいます.次のページ以降で利用する日本語評価極性辞書(名詞編)には(全角の)「1位」や「競争相手」という用語に感情の情報が与えられていることから,ここでは mecab-ipadic-NEologd 辞書を利用して作業を進めることにします.
# t = mc.Tagger() # for Windows
t = mc.Tagger('-r /dev/null -d /opt/homebrew/lib/mecab/dic/ipadic') # for macOS
sent = "今日の勝利で1位に躍進して優勝が濃厚になったことが競争相手にとっては痛手となった" # 1位の「1」は全角文字であることに注意
print(t.parse(unicodedata.normalize('NFKC', sent)))
今日 名詞,副詞可能,*,*,*,*,今日,キョウ,キョー の 助詞,連体化,*,*,*,*,の,ノ,ノ 勝利 名詞,サ変接続,*,*,*,*,勝利,ショウリ,ショーリ で 助詞,格助詞,一般,*,*,*,で,デ,デ 1 名詞,数,*,*,*,*,* 位 名詞,接尾,助数詞,*,*,*,位,イ,イ に 助詞,格助詞,一般,*,*,*,に,ニ,ニ 躍進 名詞,サ変接続,*,*,*,*,躍進,ヤクシン,ヤクシン し 動詞,自立,*,*,サ変・スル,連用形,する,シ,シ て 助詞,接続助詞,*,*,*,*,て,テ,テ 優勝 名詞,サ変接続,*,*,*,*,優勝,ユウショウ,ユーショー が 助詞,格助詞,一般,*,*,*,が,ガ,ガ 濃厚 名詞,形容動詞語幹,*,*,*,*,濃厚,ノウコウ,ノーコー に 助詞,格助詞,一般,*,*,*,に,ニ,ニ なっ 動詞,自立,*,*,五段・ラ行,連用タ接続,なる,ナッ,ナッ た 助動詞,*,*,*,特殊・タ,基本形,た,タ,タ こと 名詞,非自立,一般,*,*,*,こと,コト,コト が 助詞,格助詞,一般,*,*,*,が,ガ,ガ 競争 名詞,サ変接続,*,*,*,*,競争,キョウソウ,キョーソー 相手 名詞,一般,*,*,*,*,相手,アイテ,アイテ にとって 助詞,格助詞,連語,*,*,*,にとって,ニトッテ,ニトッテ は 助詞,係助詞,*,*,*,*,は,ハ,ワ 痛手 名詞,一般,*,*,*,*,痛手,イタデ,イタデ と 助詞,格助詞,一般,*,*,*,と,ト,ト なっ 動詞,自立,*,*,五段・ラ行,連用タ接続,なる,ナッ,ナッ た 助動詞,*,*,*,特殊・タ,基本形,た,タ,タ EOS
形態素ごとの結果を辞書形式に整えて,それをリスト化した結果として返す mecab_analysis()
関数を作成してみます.この関数の中では,形態素解析を実行するまでに文字列を半角文字列に正規化していることに注意してください.
import MeCab as mc
import pandas as pd
import unicodedata
from pprint import pprint
def mecab_analysis(text):
"""
形態素解析し,辞書のリスト形式で返す
"""
# t = mc.Tagger()
# t = mc.Tagger('-r /dev/null -d /opt/homebrew/lib/mecab/dic/ipadic') # for macOS
t = mc.Tagger('-r /dev/null -d /opt/homebrew/lib/mecab/dic/mecab-ipadic-neologd') # for macOS
text = unicodedata.normalize('NFKC', text) # 形態素解析を実行する前に半角文字へ正規化する
node = t.parseToNode(text)
words = []
while(node):
if node.surface != "": # ヘッダとフッタを除外
pos = node.feature.split(",")[0] # pos (part_of_speech) 品詞
lemma = node.feature.split(",")[6] # lemma 原型
w = {
'surface': node.surface, # 表層形
'lemma': lemma,
'pos': pos
}
words.append(w)
node = node.next
if node is None:
break
return words
sent = "今日の勝利で1位に躍進して優勝が濃厚になったことが競争相手にとっては痛手となった" # 1位の「1」は全角文字であることに注意
results = mecab_analysis(sent)
pprint(results)
[{'lemma': '今日', 'pos': '名詞', 'surface': '今日'}, {'lemma': 'の', 'pos': '助詞', 'surface': 'の'}, {'lemma': '勝利', 'pos': '名詞', 'surface': '勝利'}, {'lemma': 'で', 'pos': '助詞', 'surface': 'で'}, {'lemma': '1位', 'pos': '名詞', 'surface': '1位'}, {'lemma': 'に', 'pos': '助詞', 'surface': 'に'}, {'lemma': '躍進', 'pos': '名詞', 'surface': '躍進'}, {'lemma': 'する', 'pos': '動詞', 'surface': 'し'}, {'lemma': 'て', 'pos': '助詞', 'surface': 'て'}, {'lemma': '優勝', 'pos': '名詞', 'surface': '優勝'}, {'lemma': 'が', 'pos': '助詞', 'surface': 'が'}, {'lemma': '濃厚', 'pos': '名詞', 'surface': '濃厚'}, {'lemma': 'に', 'pos': '助詞', 'surface': 'に'}, {'lemma': 'なる', 'pos': '動詞', 'surface': 'なっ'}, {'lemma': 'た', 'pos': '助動詞', 'surface': 'た'}, {'lemma': 'こと', 'pos': '名詞', 'surface': 'こと'}, {'lemma': 'が', 'pos': '助詞', 'surface': 'が'}, {'lemma': '競争相手', 'pos': '名詞', 'surface': '競争相手'}, {'lemma': 'にとって', 'pos': '助詞', 'surface': 'にとって'}, {'lemma': 'は', 'pos': '助詞', 'surface': 'は'}, {'lemma': '痛手', 'pos': '名詞', 'surface': '痛手'}, {'lemma': 'と', 'pos': '助詞', 'surface': 'と'}, {'lemma': 'なる', 'pos': '動詞', 'surface': 'なっ'}, {'lemma': 'た', 'pos': '助動詞', 'surface': 'た'}]