空間データ分析と同様に、テキスト・データの背景にあるパターンと構造を帰納的に理解するためには、探索的データ分析 (exploratory data analysis) が行われる。
今回は、テキスト・データを用いた単語の使用頻度に基づいて、テキストのキーワード (topic) を分析し、文書の著者を予測する。
応用例として、『ザ・フェデラリスト』の著者を予測する。
電子化された大量のテキスト・データが刻一刻とメール、ウェブサイト、SNSなどを通じて蓄積されている。
ブログやSNSを分析すれば、人々の行動や意見に対する新しい洞察を得ることができる。
過去に出版された論文や書籍、公文書の電子化も大規模に進められており、データ分析により過去に研究された問題を再考する絶好の機会を与えてくれる。
統計学的文献学における最初のテキスト分析の例である『ザ・フェデラリスト (The Federalist)』のテキストを分析する。
『ザ・フェデラリスト』第1巻のタイトルページ 出典:アメリカ議会図書館
『ザ・フェデラリスト』は、ニューヨークの人々に新たに起草されたアメリカ合衆国憲法の批准を促すため、アレクサンダー・ハミルトン (Alexander Hamilton)、ジョン・ジェイ (John Jay)、ジェームズ・マディソン (James Madison) によって書かれた85篇の論文からなる。
もともとはニューヨーク州内の様々な新聞に「プブリウス (Publius)」という筆名で掲載された。
アメリカ議会図書館のウェブサイトには、判明している論文の著者が示されている。
ハミルトン:51篇
マディソン:15篇
ジョン・ジェイ:5篇
ハミルトンとマディソンの共著:3篇
残りの11論文はハミルトンかマディソンのいずれかによって書かれたが、どちらが著者なのかについては研究者の間で意見が分かれている。
以下では『フェデラリスト・ペーパー』のテキストを分析して、各篇の著者を予測する。
85篇の論文は、アメリカ議会図書館のウェブサイトからスクレープ (収集)され、fpXX.txt
として保存されている。
スクレーピング (scraping) とは、コンピュータ・プログラムを用いてウェブサイトからデータを自動で収集する方法のこと。
XX
は論文の番号で 01
から 85
まであり、それぞれのデータファイルには対応するテキスト・データが含まれている。
参考として『フェデラリスト・ペーパー』第1篇の最初と最後の文を例示する。
AFTER an unequivocal experience of the inefficiency of the subsisting federal government, you are called upon to deliberate on a new Constitution for the United States of America.
This shall accordingly constitute the subject of my next address.
データの分析に先立って、前処理 (preprocess) を行う必要がある。
tm
パッケージは R
に多くの自然言語処理 (natural language processing) 機能を提供している。
英単語間の不要なスペースを消す
異なる形態の共通の語幹をもつ単語が同じであるとわかるように接頭辞や接尾辞を取り去り語幹を残すステミング (stemming)
tm
パッケージにおける語幹化機能は、SnowballC
と呼ばれる別のパッケージを必要とする。
複数のパッケージを読み込むには、読み込みたいパッケージをコンマで区切ればよい。
## 必要な2つのパッケージをインストールする(1度だけでよい)
## install.packages("tm")
## install.packages("SnowballC")
## 必要な2つのパッケージを読み込む
library(tm, SnowballC)
## Loading required package: NLP
はじめに、VCorpus()
関数を用いて、テキストの集合であるコーパス (corpus) を R
に読み込む。
DirSource()
関数を用いてコーパスのファイル名のパターンを指定する。
引数 directory
はファイルの場所を示す。
federalist
引数 pattern
はすべてのデータファイルの名前に含まれるパターンを示す。
fp01.txt
や fp10.txt
などなので fp
を指定する。## 未加工のコーパスを読み込む
corpus.raw <- VCorpus(DirSource(directory = "federalist", pattern = "fp"))
corpus.raw
## <<VCorpus>>
## Metadata: corpus specific: 0, document level (indexed): 0
## Content: documents: 85
コーパスの前処理のために、コーパスに対して様々な自然言語処理を行うことのできる tm_map()
関数を用いる。
最初の引数:コーパスの名前
2番目の引数:テキスト変換用の関数
未加工テキストの前処理では次のような関数がよく用いられる。
tolower()
:小文字に変換する
stripWhitespace()
:スペースを取り除く
removePunctuation()
:句読点を取り除く
removeNumbers()
:数字を取り除く
removeWords()
:特定の単語を取り除く
stemDocument()
:指定された言語用に文書中の単語を語幹化する
まずは、以下のように前処理を行う。
tolower()
関数を用いてすべての文字を小文字に変換する。
tolower()
関数は、tm
パッケージではなく R
の base
パッケージ内の関数なので、content_transformer()
と呼ばれるラッパー(呼び出し用)関数を経由して用いなければならない。stripWhitespace()
関数を用いて不要なスペースを削除する。
removePunctuation()
関数で不要な句読点を取り除く.
removeNumbers()
関数で不要な数字を除外する。
## 小文字にする
corpus.prep <- tm_map(corpus.raw, content_transformer(tolower))
## スペースを取り除く
corpus.prep <- tm_map(corpus.prep, stripWhitespace)
## 句読点を取り除く
corpus.prep <- tm_map(corpus.prep, removePunctuation)
## 数字を取り除く
corpus.prep <- tm_map(corpus.prep, removeNumbers)
次に、最も頻繁に使用される単語である a
や the
などを除外する。
stopwords()
関数を用いて、入力言語に対応するストップワード(検索で無視される単語)のリストを見る。
## [1] "i" "me" "my" "myself" "we" "our"
removeWords()
関数にこのリストを使用する。二重角括弧 [[]]
と抽出する要素を示す整数を用いて、特定の論文を抽出することもできる。
加えて、content()
関数によって、選択された文書の実際のテキストを出力できる。
## [1] "among numer advantag promis wellconstruct union none"
## [2] "deserv accur develop tendenc break"
## [3] "control violenc faction friend popular govern never"
AMONG the numerous advantages promised by a well-constructed Union, none
deserves to be more accurately developed than its tendency to break and
control the violence of faction. The friend of popular governments never
すべての前処理がこれまでのコードで指定された通り次のように実行されていることがわかる。
すべての文字を小文字に変換
ハイフンやコンマなどの句読点記号を除外
単語は語幹だけの形に変換
numerous
は numer
に、promised
は promis
に、などテキスト・データを探索する手取り早い方法は、単純に単語や用語の出現頻度を数えることである。
ある文書中に特定の単語が現れる回数を用語頻度 (term frequency; tf) と呼ぶ。
用語頻度の統計量は文書-用語行列 (document-term matrix) に要約できる。
行が文書を、列が各用語を表す、長方形の配列となる。
行列の \((i, j)\) 要素は、\(i\) 番目の文書(行)の \(j\) 番目の用語(列)の数を表す。
行列の行と列を入れ替えて、行が用語、列が文書を表す用語-文書行列 (term-document matrix) に変換することもできる。
R
では、文書-用語行列は DocumentTermMatrix()
関数によって生成できる。
TermDocumentMatrix()
関数によって生成される。## <<DocumentTermMatrix (documents: 85, terms: 4849)>>
## Non-/sparse entries: 44917/367248
## Sparsity : 89%
## Maximal term length: 18
## Weighting : term frequency (tf)
DocumentTermMatrix()
関数の出力は特殊な行列なので、R
は文書-用語行列そのものではなく、その要約を出力する。
文書の数や用語の数
Sparcity
:文書-用語行列における頻度が0のエントリーの割合
Maximal term length
:用語の最大の長さ
Weighting
:行列のエントリーを重み付けする数量
この例のように、文書-用語行列は通常、疎 (sparse) である。
ほとんどの用語はほんの少数の文書に飲み現れるので、大多数のエントリーは0
『フェデラリスト・ペーパー』の場合、文書-用語行列のエントリーの89%は0
文書-用語行列の実際のエントリーの詳細を見るためには、inspect()
関数を用いる。
この関数はコーパスや文書-用語行列の詳細な情報を示す。
角括弧 []
でデータフレームの部分集合を定義する場合と同じように、行列オブジェクトの部分集合を定義できる。
例として、文書-用語行列の最初の5行と最初の8列を調べる。
## <<DocumentTermMatrix (documents: 5, terms: 8)>>
## Non-/sparse entries: 4/36
## Sparsity : 90%
## Maximal term length: 7
## Weighting : term frequency (tf)
## Sample :
## Terms
## Docs abandon abat abb abet abhorr abil abject abl
## fp01.txt 0 0 0 0 0 0 0 1
## fp02.txt 0 0 0 0 0 1 0 0
## fp03.txt 0 0 0 0 0 0 0 2
## fp04.txt 0 0 0 0 0 0 0 1
## fp05.txt 0 0 0 0 0 0 0 0
as.matrix()
関数を用いてこのオブジェクトを通常の matrix
オブジェクトに変換し、直接出力することもできる。## Terms
## Docs abandon abat abb abet abhorr abil abject abl
## fp01.txt 0 0 0 0 0 0 0 1
## fp02.txt 0 0 0 0 0 1 0 0
## fp03.txt 0 0 0 0 0 0 0 2
## fp04.txt 0 0 0 0 0 0 0 1
## fp05.txt 0 0 0 0 0 0 0 0
今回は下巻の第5章の内容に基づく。
原著 Quantitative Social Science (Princeton University Press) のウェブ・ページでデータなどをダウンロードできる。