- はじめに: 『R環境で小説のテキストマイニング』の連載シリーズ
- 形態素のワードクラウドに関するイントロダクション
- RMeCab形態素解析済みの結果の読み込み
- ワードクラウドによる形態素頻度の可視化
- 坊ちゃん第2章以降のワードクラウドによる可視化
- まとめ
- 参考資料
はじめに: 『R環境で小説のテキストマイニング』の連載シリーズ
テキストマイニングは、テキストデータから、有益な情報を取り出すデータマイニング手法の1つです。 テキストデータに対する情報解析では、自然言語処理、形態素解析、キーワード抽出、共起分析、ネットワーク可視化、機械学習、感情分析など、様々な分析手法が用いられます。 近年では、TwitterのつぶやきやSNS、地図上のクチコミなどのテキストデータも活用されています。
この記事は、夏目漱石の「坊っちゃん」が対象小説で、 テキストマイニングと形態素のワードクラウドを扱った内容となっています。
連載シリーズの目次
2. 「坊っちゃん」のテキストの前処理
3. 形態素解析と辞書設定
4. 形態素解析と複合語抽出 (ルールベース抽出、pytermextract)
5. テキストマイニングと形態素のワードクラウド
6. テキストマイニングとN-gramのネットワーク表現(章ごとの関係性とか)
7. テキストマイニングと単語の埋め込み生成(word2vecとか)
8. 文章の感情分析(感情ポジネガ分析とか、英語感情対応表とか、ML-askとか)
9. ミクロとマクロなテキスト解析〜応用篇として内容を考え中〜
この記事では、「5. テキストマイニングと形態素のワードクラウド」に関する内容をやっていきます。
まずは、実行環境
#ターミナル上のR環境 R version 4.1.2 (2021-11-01) -- "Bird Hippie" Copyright (C) 2021 The R Foundation for Statistical Computing Platform: aarch64-apple-darwin20.6.0 (64-bit) #RStudioターミナル上のR環境 R version 4.1.2 (2021-11-01) -- "Bird Hippie" Copyright (C) 2021 The R Foundation for Statistical Computing Platform: x86_64-apple-darwin17.0 (64-bit)
今回、M1 Mac・RStudioでRMeCabパッケージがうまく動作せず、 形態素解析の部分はターミナルからR実行した結果を使っています。
形態素のワードクラウドに関するイントロダクション
ワードクラウド(Wordcloud)は、 テキスト中の語彙の出現頻度をもとに、 テキスト中の頻出語を視覚的に表現する手法の1つです。 各語彙を頻度に比例する大きさで表す、視覚表現をとっています。
さて、「ワードクラウドをどのように作るか?」ということですが、
テキストの取得・前処理
テキストの形態素解析
ワードクラウドによる形態素頻度の可視化
の3ステップになります。
「1」のテキストの取得と前処理が終われば、 次に、「2」でテキストをそれぞれ語彙に分解する必要があります。 いわゆる、形態素解析のステップです。 具体的には、RMeCab + neologd辞書を使って、形態素解析していきます。
「1. テキストの取得・前処理」と「2. テキストの形態素解析」の具体的な実行方法については、 過去の記事で大変分かりやすくまとめていますので、そちらを参照してください。
さっそく、「3. ワードクラウドによる形態素頻度の可視化」のステップに進みます。
はじめに、「坊っちゃん」の第1章テキストでの形態素解析済みの結果(result1.Rds or result1.txt)を GitHubからダウンロードして、R環境に読み込むところをやります。
RMeCab形態素解析済みの結果の読み込み
.Rdsをロードする場合
.RdsファイルをR環境に読み込む場合には、一度ローカルにファイルをダウンロードする必要があります。
##形態素解析の結果(result1.Rds)をR環境にロードする #URL先の定義 Rds_path <- "https://github.com/kumeS/Blog/raw/master/R_text_analysis/R_02/result1.Rds" #ローカルディレクトリにダウンロード download.file(url=Rds_path, destfile = basename(Rds_path)) #Rdsの読み込み result1r <- readRDS(file = "result1.Rds")
.txtをロードする場合
.txtファイルの場合には、WebのURLから直接読み込むことができます。 そのため、テキストの方が手数としては少なくなります。
##形態素解析の結果(result1.txt)をR環境にロードする #URL先の定義 Txt_path <- "https://github.com/kumeS/Blog/raw/master/R_text_analysis/R_02/result1.txt" #txtの読み込み result1t <- read.table(file=Txt_path, header = T, sep = "\t")
結局は、以下のように同じ結果がロードされます。 好みで、ファイル読み込みの方法を決めてください。
#ヘッド表示 head(result1r) # parts mor #1 名詞 親譲り #2 助詞 の #3 名詞 無鉄砲 #4 助詞 で #5 名詞 小供 #6 助詞 の #詳細表示 str(result1r) #'data.frame': 4870 obs. of 2 variables: # $ parts: chr "名詞" "助詞" "名詞" "助詞" ... # $ mor : chr "親譲り" "の" "無鉄砲" "で" ... #ヘッド表示 head(result1t) # parts mor #1 名詞 親譲り #2 助詞 の #3 名詞 無鉄砲 #4 助詞 で #5 名詞 小供 #6 助詞 の #詳細表示 str(result1t) #'data.frame': 4870 obs. of 2 variables: # $ parts: chr "名詞" "助詞" "名詞" "助詞" ... # $ mor : chr "親譲り" "の" "無鉄砲" "で" ...
変数result1
の中身は、2列 x 4870行のデータフレーム形式
のデータで、
4870個の形態素(mor列)とそれに対応する品詞(parts列)の情報が含まれています。
これは、RMeCab + neologd辞書を使った形態素解析の結果です。
ワードクラウドによる形態素頻度の可視化
さて、ワードクラウドを作成するのに使う、関連パッケージをインストールしていきます。
#wordcloud2とhtmlwidgetsのインストール install.packages(c("wordcloud2", "htmlwidgets")) library(wordcloud2); library(htmlwidgets) #カラーパレット install.packages("colorspace") library("colorspace")
次に、ワードクラウドによる可視化を行う、実際のRコードを紹介します。
品詞情報をもとに、名詞のみ抽出した場合、形容詞や動詞も含めた場合、複合語判定の結果を含めた場合など、 複数パターンのワードクラウドを作成していきます。 また、「平仮名1文字の形態素を除く」とか、「形態素頻度の補正」とか、「出現数上位20%のみ抽出」とかの前処理もやっています。
品詞情報から「名詞」のみ抽出した場合のワードクラウド
まずはじめに、坊ちゃんの第1章のテキストデータを使って、 「名詞」のみ抽出した形態素の結果 に対して、ワードクラウドを実行します。
#Rdsのロード結果を使用します。 result1 <- result1r #品詞から「名詞」のみ抽出した場合 result2 <- result1[result1$parts %in% c("名詞"),] #品詞の集計 table(result2$parts) #名詞 #1292 #平仮名1文字の形態素を除く result3 <- result2[!base::grepl(pattern="^[あ-ん]$", result2$mor),] #集計 Dat <- data.frame(mor=names(table(result3$mor)), Freq=as.numeric(table(result3$mor))) #頻度1回を除く Dat <- Dat[Dat$Freq != 1,] #形態素頻度を0~1の値に補正 Dat$FreqR <- round(Dat$Freq/max(Dat$Freq), 4) #出現数上位20%のみ抽出 res <- quantile(Dat$FreqR, probs = seq(0, 1, 0.1)) Dat0 <- Dat[Dat$FreqR > as.numeric(res[9]),] #抽出の結果 dim(Dat0) #[1] 38 3 #表示 head(Dat0[order(Dat0$Freq, decreasing = T),]) # mor Freq FreqR #12 おれ 43 1.0000 #356 清 37 0.8605 #183 兄 27 0.6279 #63 もの 26 0.6047 #115 何 25 0.5814 #255 事 22 0.5116 #wordcloud2.jsによるワードクラウド作成 Dat1 <- wordcloud2(Dat0[,c("mor", "FreqR")], shape="circle", size=0.8, gridSize = 1, fontFamily="YuGothic", color = "random-light", ellipticity = 0.75, backgroundColor = "black") #ワードクラウド結果の表示 Dat1 #ワードクラウドの保存 htmlwidgets::saveWidget(Dat1, "./WordCloud_Dat0.html", selfcontained = F)
簡単にRコードの解説をします。 まず、%in%を使って、名詞だけ抽出しています。 次に、平仮名1文字の形態素を除き、単語のリストとカウントを作成しています。 そして、各前処理を行い、各単語、それぞれに対応する頻度と補正頻度を持つデータフレームを作成しています。
最終的に、ワードクラウドを実行する、wordcloud2関数には、 形態素とその補正頻度「Dat0[,c("mor", "FreqR")]」をINPUTとして与えています。 また、オプションとしては、shape、fontFamily、ellipticity、backgroundColorなどを設定しています。
品詞情報から「名詞」「形容詞」「動詞」を抽出した場合のワードクラウド
坊ちゃんの第1章のテキストデータを使って、 「名詞」と「形容詞」と「動詞」を抽出した形態素の結果 に対して、ワードクラウドを実行します。
#Rdsのロード結果を使用します。 result1 <- result1r #品詞から「名詞」と「形容詞」と「動詞」を抽出 result2 <- result1[result1$parts %in% c("名詞", "形容詞", "動詞"),] #品詞の集計 table(result2$parts) #形容詞 動詞 名詞 # 87 775 1292 #平仮名1文字の形態素を除く result3 <- result2[!base::grepl(pattern="^[あ-ん]$", result2$mor),] #品詞の集計 table(result3$parts) #形容詞 動詞 名詞 # 87 774 1255 #集計 Dat <- data.frame(mor=names(table(result3$mor)), Freq=as.numeric(table(result3$mor))) #頻度1回を除く Dat <- Dat[Dat$Freq != 1,] #形態素頻度を0~1の値に補正 Dat$FreqR <- round(Dat$Freq/max(Dat$Freq), 4) #出現数上位20%のみ抽出 res <- quantile(Dat$FreqR, probs = seq(0, 1, 0.1)) Dat0 <- Dat[Dat$FreqR > as.numeric(res[9]),] #抽出の結果 dim(Dat0) #[1] 52 3 #表示 head(Dat0[order(Dat0$Freq, decreasing = T),]) # mor Freq FreqR #57 する 89 1.0000 #173 云う 50 0.5618 #16 いる 46 0.5169 #22 おれ 43 0.4831 #98 なる 37 0.4157 #542 清 37 0.4157 #wordcloud2.jsによるワードクラウド作成 Dat1 <- wordcloud2(Dat0[,c("mor", "FreqR")], shape="circle", size=0.8, gridSize = 1, fontFamily="YuGothic", color = "random-light", ellipticity = 0.75, backgroundColor = "black") #ワードクラウド結果の表示 Dat1 #ワードクラウドの保存 htmlwidgets::saveWidget(Dat1, "./WordCloud_Dat1.html", selfcontained = F)
品詞情報から「名詞」と「複合語」を抽出した場合のワードクラウド
坊ちゃんの第1章のテキストデータを使って、 「名詞」と「複合語」を抽出した形態素の結果 に対して、ワードクラウドを実行します。
#Rdsのロード結果を使用します。 result1 <- result1r #複合語抽出: Compound_calc()関数を使います source("https://raw.githubusercontent.com/kumeS/Blog/master/R_text_analysis/R_03/Compound_calc.R") #実行 result1c <- Compound_calc(result = result1) #品詞から「名詞」と「形容詞」と「動詞」を抽出 result2 <- result1c[result1c$parts %in% c("名詞", "複合語"),] #品詞の集計 table(result2$parts) #複合語 名詞 # 137 1003 #平仮名1文字の形態素を除く result3 <- result2[!base::grepl(pattern="^[あ-ん]$", result2$mor),] #品詞の集計 table(result3$parts) #複合語 名詞 # 137 972 #集計 Dat <- data.frame(mor=names(table(result3$mor)), Freq=as.numeric(table(result3$mor))) #頻度1回を除く Dat <- Dat[Dat$Freq != 1,] #形態素頻度を0~1の値に補正 Dat$FreqR <- round(Dat$Freq/max(Dat$Freq), 4) #出現数上位20%のみ抽出 res <- quantile(Dat$FreqR, probs = seq(0, 1, 0.1)) Dat0 <- Dat[Dat$FreqR > as.numeric(res[9]),] #抽出の結果 dim(Dat0) #[1] 30 3 #表示 head(Dat0[order(Dat0$Freq, decreasing = T),]) # mor Freq FreqR #12 おれ 42 1.0000 #367 清 37 0.8810 #71 もの 26 0.6190 #189 兄 25 0.5952 #121 何 23 0.5476 #264 事 22 0.5238 #wordcloud2.jsによるワードクラウド作成 Dat1 <- wordcloud2(Dat0[,c("mor", "FreqR")], shape="circle", size=0.8, gridSize = 1, fontFamily="YuGothic", color = colorspace::rainbow_hcl(nrow(Dat0), c = 60, l = 60), ellipticity = 0.75, backgroundColor = "black") #ワードクラウド結果の表示 Dat1 #ワードクラウドの保存 htmlwidgets::saveWidget(Dat1, "./WordCloud_Dat2_1st.html", selfcontained = F)
坊ちゃん第2章以降のワードクラウドによる可視化
次に、第2章以降でワードクラウドを試してみた結果を紹介します。
坊ちゃんの第2章のテキストデータを使って、 「名詞」と「複合語」を抽出した形態素の結果 に対して、ワードクラウドを実行します。
上記の実行が冗長なので、 ワークフローを自作関数化して(wdCloud.R関数という名前)、 実行を簡略化しています。
坊ちゃん第2章のワードクラウド
#txtファイルを読み込んで使用します。 Txt_path <- "https://github.com/kumeS/Blog/raw/master/R_text_analysis/R_02/result2.txt" result1 <- read.table(file=Txt_path, header = T, sep = "\t") #wdCloud.Rのロード source("https://raw.githubusercontent.com/kumeS/Blog/master/R_text_analysis/R_04/wdCloud_test.R") #ワードクラウド実行 Dat1 <- wdCloud.R(result1) #ワードクラウド結果の表示 Dat1 #ワードクラウドの保存 htmlwidgets::saveWidget(Dat1, "./WordCloud_Dat2_2nd.html", selfcontained = F)
坊ちゃん第3章のワードクラウド
続いて、坊ちゃん第3章のワードクラウドです。
#txtファイルを読み込んで使用します。 Txt_path <- "https://github.com/kumeS/Blog/raw/master/R_text_analysis/R_02/result3.txt" result1 <- read.table(file=Txt_path, header = T, sep = "\t") #wdCloud.Rのロード source("https://raw.githubusercontent.com/kumeS/Blog/master/R_text_analysis/R_04/wdCloud_test.R") #ワードクラウド実行 Dat1 <- wdCloud.R(result1) #ワードクラウド結果の表示 Dat1 #ワードクラウドの保存 htmlwidgets::saveWidget(Dat1, "./WordCloud_Dat2_3rd.html", selfcontained = F)
同じなので、以下省略。。。
https://kumes.github.io/Blog/R_text_analysis/R_04/WordCloud_Dat2_4th.html
https://kumes.github.io/Blog/R_text_analysis/R_04/WordCloud_Dat2_5th.html
https://kumes.github.io/Blog/R_text_analysis/R_04/WordCloud_Dat2_6th.html
https://kumes.github.io/Blog/R_text_analysis/R_04/WordCloud_Dat2_7th.html
https://kumes.github.io/Blog/R_text_analysis/R_04/WordCloud_Dat2_8th.html
https://kumes.github.io/Blog/R_text_analysis/R_04/WordCloud_Dat2_9th.html
https://kumes.github.io/Blog/R_text_analysis/R_04/WordCloud_Dat2_10th.html
https://kumes.github.io/Blog/R_text_analysis/R_04/WordCloud_Dat2_11th.html
坊ちゃん第1〜11章のワードクラウドの結果まとめ
過去に坊ちゃんを読んだことなるような、無いような、内容はほとんど覚えてませんので、 ワードクラウド見た感じの印象をツラツラと書いてます。
全体を通して、「おれ」はよく出てきてますね。「おれ」中心の話なんでしょうね。
第1章は、「おれ」「清」「兄」とかが目立つ。清が兄なんかな、分からんけど。
第2章はなんか和茶和茶してますね。中学校が舞台なのか、教師とか校長とか、山嵐も出てくるようです。
第3章のクラウドはやや控えめですね。学校の隣に東京とあり、誰か転校生がやってくるのか? ワードクラウドでは、語彙の位置関係は関係ないですけども。
第4章は「バッタ」と「宿直」、第5章は「赤シャツ」、第6章は「山嵐」、第7章は「模試」が目立ちます。 模試とあるので試験勉強してのかな。山嵐ってなんだっけ?風のこと?柔道の技のこと?
第8章で、もう一度「赤シャツ」が出てくる、「婆さん」「月給」もでてくるようだ。 「月給」とか、なんだか現実的な話っぽいね。
さらに、第9章で「うらなり君」と「送別会」、第10章で「喧嘩」、 第11章ではまたも「山嵐」で、「新聞屋・新聞」が新しく出てくる。 転校生の「うらなり君」喧嘩したのか?最後に、新聞バイトしてるのか?謎は深まるばかり。。 ワードクラウドを見ただけだと、テキトーな考察になってしまいましたね。
まとめ
今回は、テキストマイニングの一例として、 坊ちゃんの各章のテキストデータをワードクラウドで可視化してみました。
結構簡単にワードクラウドを実行できるので、 色々な条件で見方を変えて、ぜひ色々と試してみてください。