always one step forward

MeCab+RMeCabで「走れメロス」を形態素解析

MeCab+RMeCabで「走れメロス」を形態素解析。特に最終目的もなく、いくつか試しただけながら、MeCabによる形態素解析の雰囲気が掴めてよかった。

環境

  • MacOS X Mavericks 10.9.2)
  • R 3.0.3
  • MeCab 0.996
  • RMeCab_0.9995 (R-3.0.3)

環境構築まではこちらを:MeCab+RMeCabインストール - OS X v10.9.2

使用テキストデータ

メロスは激怒した。

必ず、かの邪智暴虐の王を除かなければならぬと決意した。

メロスには政治がわからぬ。

...

勇者は、ひどく赤面した。

もちろん、青空文庫でもテキストそのものは入手できる。ボランティア皆さんに感謝

まずとにかく形態素解析

1ファイルであればRMeCabFreq関数が便利。出力がすでにRのデータフレームになっていて、その後が扱いやすい。下記のように得られるデータフレームresが全ての出発点

# 形態素解析の結果をデータフレームresへ
> res <- RMeCabFreq("merosu.txt")

file = merosu.txt 
length = 1306 # 形態素の数

# 例として最初の10データを表示。Info1/2は品詞情報、Freqは登場頻度
> res[1:10,]

       Term    Info1 Info2 Freq
1        え フィラー     *    1
2        と フィラー     *    3
3  いくぶん     副詞  一般    1
4  いよいよ     副詞  一般    2
5    うんと     副詞  一般    2
6  おいおい     副詞  一般    1
7    かっと     副詞  一般    1
8    きっと     副詞  一般    3
9  きらきら     副詞  一般    1
10 ごろりと     副詞  一般    1

# 最後付近のデータを表示
> res[1300:1306,]

1300   その 連体詞     *   21
1301 そんな 連体詞     *    1
1302 どんな 連体詞     *    2
1303 ほんの 連体詞     *    1
1304   同じ 連体詞     *    2
1305 大きな 連体詞     *    2
1306     或 連体詞     *    1

# 一番左列の数値:Rのデータフレームに自動的につく通し番号。解析そのものにはあまり関係なし

小説に含まれる形態素の品詞

  • 平たく言えば "「走れメロス」に含まれる単語の品詞はどんなものがあるか?"
  • 合わせて "そもそもMeCabがどんな品詞情報を返してくれるのか" もある程度わかる
# データフレームresの"Info1"列に含まれる値を、重複除去して返す
> unique(res$Info1)

 [1] "フィラー" "副詞"     "助動詞"   "助詞"     "動詞"     "名詞"     "形容詞"   "感動詞"   "接続詞"  
[10] "接頭詞"   "記号"     "連体詞" 
  • 当然、得られる品詞情報は、用語に紐づくもの
  • 形態素解析で得られるその用語は、使用する辞書(の充実ぐあい)に依存する
  • MeCabと合わせて別途インストールしたIPA辞書は、現在も、このような形態素解析で"お供"にする辞書としては標準的といわれるもののようなので、まあ問題ないでしょう
    • NAIST-jdicという後継辞書も公開されている。これを参照した場合で比較するのもちょっと面白そう
  • 特定分野での分析を行うなら、それに加えてユーザ辞書の拡充が必要
    • 逆に言えば、ユーザ辞書を充実させれば、解析の仕組みそのものはほぼ何も変えずに適用できるとも言える

文章の数は?

  • "記号"をカウントしてみると「。」の数=458
    • merosu.txtの行数と一致。これが文章の数といえる
  • ちなみに(鍵かっこ「」の)会話部分は62箇所あるともわかる
# resの2列目が"記号"であるデータを抽出。res[,2]で"Info1"列を参照
> res[res[,2]=="記号",]

        Term    Info1       Info2   Freq
1288   ――      記号          一般      2
1289   々     記号          一般      6
1290   !     記号          一般      12
1291   ?     記号          一般      2
1292   。     記号          句点      458
1293   」     記号          括弧閉   62
1294   「     記号          括弧開   62
1295   、     記号          読点      555

とりあえず名詞に着目

# 名詞だけを取り出してデータフレームres_nounへ
> res_noun <- res[res[,2]=="名詞",]

# 登場する名詞の数
> nrow(res_noun)
656

# とりあえず10個表示
> res_noun[1:10,]

          Term Info1    Info2 Freq
553     お詫び  名詞 サ変接続    1
554 ひとり合点  名詞 サ変接続    1
555     一ぱい  名詞 サ変接続    4
556       一撃  名詞 サ変接続    1
557       一睡  名詞 サ変接続    1
558       一緒  名詞 サ変接続    1
559       乱心  名詞 サ変接続    2
560       仕事  名詞 サ変接続    1
561       仕度  名詞 サ変接続    4
562       仰天  名詞 サ変接続    1

# 2回以上登場する名詞の数。res[,4]で"Freq"列を参照
> nrow(res_noun <- res[res[,2]=="名詞" & res[,4] > 1,])
232 
  • Freq=1(小説中に一度しか登場しない)、いわゆるロングテールのテール側の名詞をどうするか?
    • 小説を特徴づける単語を探したい場合、Freq=1の名詞に着目するのもありだと思う。今回は除外し、Freq=2以上の名詞だけを抽出
    • いわゆるTF-IDFの考慮:「登場頻度だけでなく、"他文書には登場しないが、この文書には登場する語"を重視する」という側面でみてもおもしろそう。この場合、自然と、複数文書での比較が前提になる

単純に、その作品によく出てくる単語は何だろう、という興味から、登場する名詞を登場頻度順にソートしてみる

# res_nounをFreqで降順ソート
> res_noun[rev(order(res_noun$Freq)),]

                 Term Info1          Info2 Freq
1189               の  名詞         非自立   78
1036               私  名詞         代名詞   76
662            メロス  名詞           一般   73
1024           おまえ  名詞         代名詞   20
683                人  名詞           一般   20
707                友  名詞           一般   18
891                王  名詞           一般   17
1197               事  名詞         非自立   14
658  セリヌンティウス  名詞           一般   14
1193             よう  名詞         非自立   13
1033               君  名詞         代名詞   13
1175               三  名詞             数   12
1040             いま  名詞       副詞可能   12
895                男  名詞           一般   12
756                妹  名詞           一般   12
(以下省略)
  • 「おまえ」「友」「王」などはたしかに納得
  • 一人称は「私」でほぼ統一されているのだろうな、という点もわかる
  • もし深く分析をすすめるなら、同じ名詞でも、Info2 = "非自立" "数" などは除外してもよさそう。現時点ではとりあえずこのまま

名詞の種類は?

「名詞の種類」とは曖昧な表現だけれど、同じ名詞でも、以下のような種別がさらに可能であるということ

# "Info2"列に何が含まれているか
> unique(res_noun$Info2)
 [1] "サ変接続"       "ナイ形容詞語幹" "一般"           "代名詞"         "副詞可能"       "固有名詞"      
 [7] "形容動詞語幹"   "接尾"           "数"             "非自立"        
>        Term Info1    Info2 Freq
> 662  メロス  名詞     一般   73
> 1077 メロス  名詞 固有名詞    3

> 601              激怒  名詞       サ変接続    2
  • よく見ると、同じ名詞「メロス」でも、一般名詞or固有名詞という分け方が得られている
    • これは、不思議というか、どういう基準で分かれたのかはちょっと気になる。おそらく前後の語との関連だろう
  • 「激怒」はたしかに名詞だけれど、「激怒する」とサ変接続して動詞になる語である。動詞寄りの名詞とみなしてよさそう

動詞はどうか

# 動詞は359個
> nrow(res_verb <- res[res[,2]=="動詞",])
359
# 2回以上登場する動詞
> nrow(res_verb <- res[res[,2]=="動詞" & res[,4] > 1,])
129
# けっこう多いので「7回以上登場」まで条件を絞った
> nrow(res_verb <- res[res[,2]=="動詞" & res[,4] > 6,])
[1] 28

# 28語を登場頻度降順でソート
> res_verb[rev(order(res_verb$Freq)),] # sorting
        Term Info1  Info2 Freq
229     する  動詞   自立   73
538     いる  動詞 非自立   50
197     れる  動詞   接尾   27
250     なる  動詞   自立   26
551     来る  動詞 非自立   25
492     走る  動詞   自立   24
541   くれる  動詞 非自立   20
408     殺す  動詞   自立   17
546     やる  動詞 非自立   13
478     言う  動詞   自立   13
544     なる  動詞 非自立   12
301   出来る  動詞   自立   12
407     殴る  動詞   自立   11
290   信じる  動詞   自立   11
196   られる  動詞   接尾   11
404     死ぬ  動詞   自立   10
353     待つ  動詞   自立    9
346     帰る  動詞   自立    9
200     ある  動詞   自立    9
552     行く  動詞 非自立    8
548   下さる  動詞 非自立    8
447     笑う  動詞   自立    8
410     沈む  動詞   自立    8
542   しまう  動詞 非自立    7
432     疑う  動詞   自立    7
402     歩く  動詞   自立    7
344     居る  動詞   自立    7
208 おくれる  動詞   自立    7
  • だいぶ小説の特徴が出ている
    • 「する」は「激怒する」などサ変名詞を受けることもあり高頻度
    • やっぱり「走る」多いですね〜。ほかに「出来る」「殴る」「信じる」「待つ」など
    • これら動詞だけを挙げて「連想する小説は?」と道行く人へ聞くと、結構な確率で「走れメロス」が返ってきそうだ
  • 「小説を特徴づける品詞は何か?」
    • こんな解析をする前は何となく「名詞、固有名詞」と思っていた。たしかにそうだろうけれど、動詞も、その役を演じるのに充分と言うか、その作品の"色"が出やすい品詞だなと初めて感じた

一応グラフも

  • Rなので、データフレームを簡単に(=そんなに加工せずとも)プロットできる。あまり凝ってもいないけれど matplot してみた
    • もちろんヒストグラム hist() や棒グラフ barplot() でも合っていると思う
  • 最近ならgoogleVisがまさにRとの親和性高い可視化ライブラリ
    • たとえばBar chartなどだと表現しやすそう。BIという感じでは到底ないけれど
# res_verb(データ28個)に対して rainbow を割り当て
> k.col <- rainbow(nrow(res_verb))
# 各行のFreqをプロット
> matplot(1:nrow(res_verb), res_verb[,4], type="n")
> for(i in 1:nrow(res_verb)){matlines(i, res_verb[i,4], type="h" ,col=k.col[i], lwd=5)}
# 凡例を追加
> legend(1, max(res_verb$Freq), legend=res_verb$Term, col=k.col, bty="n",lwd=5, cex=0.5)

 MeCab+RMeCab - Major verbs in 走れメロス

N-gram

Nグラムも一応見てみる。わかりやすく、名詞と動詞に絞った。

バイグラム(bi-gram、N=2)

# データフレームtextgramへ格納
> textgram <- Ngram("merosu.txt", N = 2, type = 1, pos = c("名詞", "動詞"))

# Freq降順(多い順)でソート、データフレームtextgram_orderへ格納
> textgram_order <- textgram[rev(order(textgram$Freq)),])

# 先頭15個を表示
> head(textgram_order,15)
             Ngram Freq
424        [-]   10
2071     [走る-]    8
1203   [帰る-来る]    8
1532   [殺す-れる]    7
52       [いる-]    7
1437     [来る-]    6
790      [-殺す]    6
215    [する-いる]    6
56   [いる-メロス]    6
2168     [-沈む]    5
1782   [-信じる]    5
714        [-]    5
503      [やる-]    5
346    [なる-いる]    5
75       [いる-]    5
  • 動詞などの活用語は原形でとったため、[帰る-来る] などと得られる。元は「帰って来る(来た)」と書かれている箇所

トライグラム(tri-gram、N=3)

> textgram <- Ngram("merosu.txt", N = 3, type = 1, pos = c("名詞", "動詞"))
> textgram_order <- textgram[rev(order(textgram$Freq)),])
> head(textgram_order,20)

                        Ngram Freq
1838             [-走る-]    3
874            [-出来る-]    3
827                [--]    3
2461             [-殴る-]    2
2438         [-小降り-なる]    2
2401 [釣り上げる-られる-ゆく]    2
2318         [走る--やめる]    2
2316           [走る-いる-]    2
2119           [置く-行く-]    2
2114           [-打つ-れる]    2
2077           [笑う-れる-]    2
2035         [-殴る-くれる]    2
2015             [--抱擁]    2
2009           [-信頼-する]    2
2007       [-信じる-られる]    2
2006       [-信じる-くれる]    2
1953           [-覚める-]    2
1949         [眠る--覚める]    2
1718         [殴る-くれる-]    2
1689         [-シラクス-]    2
  • 「〜の為に走るの〜」が3箇所登場。など、どんな「語のつながり」が繰り返し見られるか、などがすぐわかる

その他おもしろそうな分析

  • 共起語(共出現語)
    • 「メロス」の近くにある動詞はどんなものが多いか、「王」の前後にはどんな名詞が来ているかなど
  • 作者の癖発見
    • 文章数の割に特定の助詞の出現確率が多いな、固有名詞の使用頻度、使われている名詞・動詞の数、など
  • 同じ作者の異なる作品比較