Permalink
Cannot retrieve contributors at this time
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
425 lines (312 sloc)
19.2 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- | |
title: "クイック・スタートガイド" | |
output: | |
html_document: | |
toc: true | |
--- | |
```{r, echo = FALSE} | |
knitr::opts_chunk$set(collapse = FALSE, comment = "##") | |
``` | |
本ページは[Quick Start Guide](../quickstart.html)の日本語訳であり,英語のテキスト分析を通じて**quanteda**の基本的な使い方を説明する.日本語の分析法に関しては,以下のページを参照. | |
* [事例: 衆議院外務委員会の議事録](examples/japanese_speech_ja.html) | |
* [事例: 2017年総選挙に関するツイート](examples/japanese_twitter_ja.html) | |
# パッケージのインストール {#installing-the-package} | |
**quanteda**は[CRAN](https://CRAN.R-project.org/package=quanteda)からインストールできる.GUIのRパッケージインストーラを使用してインストールするか,次のコマンドを実行する. | |
```{r, eval = FALSE} | |
install.packages("quanteda") | |
``` | |
GitHubから最新の開発バージョンをインストールする方法については,https://github.com/quanteda/quanteda を参照. | |
## インストールが推奨されるパッケージ {#additional-recommended-packages} | |
**quanteda**には連携して機能を拡張する一連のパッケージがあり,それらをインストールすることが推奨される. | |
* [**readtext**](https://github.com/quanteda/readtext):多くの入力形式からテキストデータをRに簡単に読み込むパッケージ | |
* [**spacyr**](https://github.com/kbenoit/spacyr):Pythonの[spaCy](https://spacy.io)ライブラリを使用した自然言語解析のためのパッケージで,品詞タグ付け,固有表現抽出,および係り受け関係の解析などができる | |
* [**quanteda.corpora**](https://github.com/quanteda/quanteda.corpora):**quanteda**の本記事内の説明で使用する追加のテキストデータ | |
```{r eval = FALSE} | |
devtools::install_github("quanteda/quanteda.corpora") | |
``` | |
* [**LIWCalike**](https://github.com/kbenoit/quanteda.dictionaries): [Linguistic Inquiry and Word Count](http://liwc.wpengine.com) (LIWC) アプローチによるテキスト分析のR実装 | |
```{r eval = FALSE} | |
devtools::install_github("kbenoit/quanteda.dictionaries") | |
``` | |
# コーパスの作成 {#creating-a-corpus} | |
まず,**quanteda**を読み込んで,パッケージの関数とデータにアクセスできるようにする. | |
```{r, message = FALSE} | |
library(quanteda) | |
``` | |
## 利用可能なコーパス {#currently-available-corpus-sources} | |
**quanteda**にはテキストを読み込むためのシンプルで強力なパッケージ,[**readtext**](https://github.com/kbenoit/readtext)があります.このパッケージの`readtext()`は,ローカス・ストレージやインターネットからファイル読み込み,`corpus()`にデータ・フレームを返す. | |
`readtext()`で利用可能なファイルやデータの形式: | |
* テキスト(`.txt`)ファイル | |
* コンマ区切り値(`.csv`)ファイル | |
* XML形式のデータ | |
* JSON形式のFacebook APIのデータ | |
* JSON形式のTwitter APIのデータ | |
* 一般的なJSONデータ | |
**quanteda**のコーパスを生成する関数である `corpus()`は,以下の種類のデータを読み込むことができる. | |
* 文字列ベクトル(例:**readtext**以外のツールを使用して読み込んだテキスト) | |
* **tm**パッケージの `VCorpus`コーパスオブジェクト | |
* テキスト列と他の文書に対応したメタデータを含むデータ・フレーム | |
### 文字列からコーパスを作成 {#building-a-corpus-from-a-character-vector} | |
コーパスを作成する最も簡単な方法は,`corpus()`を用いて,すでにRに読み込まれた文字列ベクトル作成することである.文字列ベクトルをRに取り込む方法はさまざまなので,高度なRユーザーは,コーパスをいろいろな方法で作り出せる. | |
次の例では,**quanteda**パッケージに含まれているイギリスの政党が2010年の総選挙のために発行したマニフェストのテキストデータ(`data_char_ukimmig2010`)からコーパスを作成している. | |
```{r} | |
corp_uk <- corpus(data_char_ukimmig2010) # テキストからコーパスを作成 | |
summary(corp_uk) | |
``` | |
コーパスを作成したあとでも,`docvars`を用いると,必要に応じて文書に対応した変数をこのコーパスに追加することができる. | |
たとえば,Rの`names()`関数を使って文字ベクトル(`data_char_ukimmig2010`)の名前を取得し,これを文書変数(`docvar()`)に追加することができる. | |
```{r} | |
docvars(corp_uk, "Party") <- names(data_char_ukimmig2010) | |
docvars(corp_uk, "Year") <- 2010 | |
summary(corp_uk) | |
``` | |
### readtextパッケージを用いたファイルの読み込み {#loading-in-files-using-the-readtext-package} | |
```{r, eval=FALSE} | |
require(readtext) | |
# Twitter json | |
dat_json <- readtext("~/Dropbox/QUANTESS/social media/zombies/tweets.json") | |
corp_twitter <- corpus(dat_json) | |
summary(corp_twitter, 5) | |
# generic json - needs a textfield specifier | |
dat_sotu <- readtext("~/Dropbox/QUANTESS/Manuscripts/collocations/Corpora/sotu/sotu.json", | |
textfield = "text") | |
summary(corpus(dat_sotu), 5) | |
# text file | |
dat_txtone <- readtext("~/Dropbox/QUANTESS/corpora/project_gutenberg/pg2701.txt", cache = FALSE) | |
summary(corpus(dat_txtone), 5) | |
# multiple text files | |
dat_txtmultiple1 <- readtext("~/Dropbox/QUANTESS/corpora/inaugural/*.txt", cache = FALSE) | |
summary(corpus(dat_txtmultiple1), 5) | |
# multiple text files with docvars from filenames | |
dat_txtmultiple2 <- readtext("~/Dropbox/QUANTESS/corpora/inaugural/*.txt", | |
docvarsfrom = "filenames", sep = "-", | |
docvarnames = c("Year", "President")) | |
summary(corpus(dat_txtmultiple2), 5) | |
# XML data | |
dat_xml <- readtext("~/Dropbox/QUANTESS/quanteda_working_files/xmlData/plant_catalog.xml", | |
textfield = "COMMON") | |
summary(corpus(dat_xml), 5) | |
# csv file | |
write.csv(data.frame(inaug_speech = texts(data_corpus_inaugural), | |
docvars(data_corpus_inaugural)), | |
file = "/tmp/inaug_texts.csv", row.names = FALSE) | |
dat_csv <- readtext("/tmp/inaug_texts.csv", textfield = "inaug_speech") | |
summary(corpus(dat_csv), 5) | |
``` | |
## コーパスオブジェクトの使い方 {#how-a-quanteda-corpus-works} | |
### コーパスの原理 {#corpus-principles} | |
**quanteda**のコーパスは,元の文書をユニコード(UTF-8)に変換し,文書に対するメタデータと一緒に格納しすることで、ステミングや句読点の削除などの処理よって変更されないテキストデータの静的な保管庫になるように設計されている.これによって,コーパスから文書を抽出して新しいオブジェクトを作成した後でも,コーパスには元のデータが残り,別の分析を,同じコーパスを用いて行うことができる. | |
コーパスから文書を取り出すためには,`texts()`と呼ばれる関数を使用する. | |
```{r} | |
texts(data_corpus_inaugural)[2] | |
``` | |
`summary()`により,コーパス内のテキストの要約を行うことができる. | |
```{r} | |
data(data_corpus_irishbudget2010, package = "quanteda.textmodels") | |
summary(data_corpus_irishbudget2010) | |
``` | |
`summary()`の出力をデータ・フレームとして保存し,基本的な記述統計を描画することができる. | |
```{r, fig.width = 8} | |
tokeninfo <- summary(data_corpus_inaugural) | |
if (require(ggplot2)) | |
ggplot(data = tokeninfo, aes(x = Year, y = Tokens, group = 1)) + | |
geom_line() + | |
geom_point() + | |
scale_x_continuous(labels = c(seq(1789, 2017, 12)), breaks = seq(1789, 2017, 12)) + | |
theme_bw() | |
# Longest inaugural address: William Henry Harrison | |
tokeninfo[which.max(tokeninfo$Tokens), ] | |
``` | |
## コーパスに対する操作 {#tools-for-handling-corpus-objects} | |
### コーパスの結合 {#adding-two-corpus-objects-together} | |
`+`演算子を用いると,簡単に二個のコーパスを連結できます.コーパスが異なる構造を持つ場合でも,文書変数が失われることはなく,コーパスのメタデータも引き継がれる. | |
```{r} | |
library(quanteda) | |
corp1 <- corpus(data_corpus_inaugural[1:5]) | |
corp2 <- corpus(data_corpus_inaugural[53:58]) | |
corp3 <- corp1 + corp2 | |
summary(corp3) | |
``` | |
### コーパスから文書を抽出 {#subsetting-corpus-objects} | |
`corpus_subset()`により,文書変数に適用される論理条件に基づいて文書を抽出することができる. | |
```{r} | |
summary(corpus_subset(data_corpus_inaugural, Year > 1990)) | |
summary(corpus_subset(data_corpus_inaugural, President == "Adams")) | |
``` | |
## コーパス内の文書の探索 {#exploring-corpus-texts} | |
`kwic()`(keywords-in-context)は単語の検索を行い,その単語が現れる文脈を表示する. | |
```{r, tidy=TRUE} | |
kwic(data_corpus_inaugural, pattern = "terror") | |
``` | |
```{r} | |
kwic(data_corpus_inaugural, pattern = "terror", valuetype = "regex") | |
``` | |
```{r} | |
kwic(data_corpus_inaugural, pattern = "communist*") | |
``` | |
上記の要約では,"Year"と"President"は各文書に結び付けられた変数であり,`docvars()`によってそれらにアクセスできる. | |
```{r} | |
head(docvars(data_corpus_inaugural)) | |
``` | |
[**quanteda.corpora**](https://github.com/quanteda/quanteda.corpora)をインストールすることで,より多くのコーパスを試すことができる. | |
# コーパスから特長を抽出 {#extracting-features-from-a-corpus} | |
文書のスケーリングなどの統計分析を行うためには,それぞれの文書の特長をまとめた行列を作成する必要があり,**quanteda**では,このような行列を生成するために `dfm()`を使いる. dfmは*document-feature matrix*の略で,行が文書(document),列が特長(feature)となる行列である.行と列をこのように定義する理由は,データ分析では行が分析単位になり,各列が分析対象になる変数となるのが一般的だからである.多くのソフトウェアでは,この行列を*document-term matrix*と呼ぶが,**quanteda**が語(term)でなはく特長(feature)という用語を使うのは,特長のほうが一般性を持つからで,テキスト分析では,単語,語幹,単語の集合,Nグラム,品詞など様々なものが文書の特長となる. | |
## 文書のトークン化 {#tokenizing-texts} | |
テキストを簡単にトークン化するために,**quanteda**は `tokens()`と呼ばれる強力なコマンドを提供する.この関数は,文字ベクトルのトークンのリストからなるオブジェクトを生成する.このオブジェクトでは,リストの一つ一つの要素は入力された文書に対応している. | |
`tokens()`は保守的に設計されており、ユーザーが明示的に指示を与えないかぎりは,要素を削除しない. | |
```{r} | |
txt <- c(text1 = "This is $10 in 999 different ways,\n up and down; left and right!", | |
text2 = "@kenbenoit working: on #quanteda 2day\t4ever, http://textasdata.com?page=123.") | |
tokens(txt) | |
tokens(txt, remove_numbers = TRUE, remove_punct = TRUE) | |
tokens(txt, remove_numbers = FALSE, remove_punct = TRUE) | |
tokens(txt, remove_numbers = TRUE, remove_punct = FALSE) | |
tokens(txt, remove_numbers = FALSE, remove_punct = FALSE) | |
tokens(txt, remove_numbers = FALSE, remove_punct = FALSE, remove_separators = FALSE) | |
``` | |
また,`tokens()`には個々の文字をトークン化するオプションもある. | |
```{r} | |
tokens("Great website: http://textasdata.com?page=123.", what = "character") | |
tokens("Great website: http://textasdata.com?page=123.", what = "character", | |
remove_separators = FALSE) | |
``` | |
もしくは,一文ごとにトークン化するオプションもある. | |
```{r} | |
# sentence level | |
tokens(c("Kurt Vongeut said; only assholes use semi-colons.", | |
"Today is Thursday in Canberra: It is yesterday in London.", | |
"En el caso de que no puedas ir con ellos, ¿quieres ir con nosotros?"), | |
what = "sentence") | |
``` | |
## 文書行列の作成 {#constructing-a-document-feature-matrix} | |
データからすぐに文書行列を作成したい場合は、`dfm()`に直接文字列ベクトルもしくはコーパスを渡すと、自動的にトークン化が行われ。`dfm()`は、デフォルトで大文字から小文字への置換や,句読点を除去などの操作を適用する.また,`dfm()`から`tokens()`の全てのオプションを利用できる. | |
```{r} | |
corp_inaug_post1990 <- corpus_subset(data_corpus_inaugural, Year > 1990) | |
# make a dfm | |
dfmat_inaug_post1990 <- dfm(corp_inaug_post1990) | |
dfmat_inaug_post1990[, 1:5] | |
``` | |
以下の例では`dfm()`の追加のオプションを用いて、ストップワードの削除(`remove`)と語のステミング(`stem`)を行っている. | |
```{r} | |
# make a dfm, removing stopwords and applying stemming | |
dfmat_inaug_post1990 <- dfm(dfmat_inaug_post1990, | |
remove = stopwords("english"), | |
stem = TRUE, remove_punct = TRUE) | |
dfmat_inaug_post1990[, 1:5] | |
``` | |
`remove`によって,文書行列から除外するトークンを指定する.`stopwords()`は,幾つかの言語で定義されたストップワードのリストを返す. | |
```{r} | |
head(stopwords("en"), 20) | |
head(stopwords("ru"), 10) | |
head(stopwords("ar", source = "misc"), 10) | |
``` | |
### 文書行列の表示 {#viewing-the-document-feature-matrix} | |
RStudioの"Environment"パネル,またはRの`View()`を用いることで,dfmに格納された値を見ることができる. | |
```{r warning=FALSE, fig.width = 8, fig.height = 8} | |
dfmat_uk <- dfm(data_char_ukimmig2010, remove = stopwords("english"), remove_punct = TRUE) | |
dfmat_uk | |
``` | |
頻度が最も高い特長を見るには,`topfeatures()`を用いる. | |
```{r} | |
topfeatures(dfmat_uk, 20) # 20 most frequent words | |
``` | |
dfmを`textplot_wordcloud()`に渡すことで,ワードクラウドを描画できる.この関数は,オブジェクトや引数を**wordcloud**パッケージの`wordcloud()`に渡すので,ワードクラウドの表示を変更できる. | |
```{r warning=FALSE, fig.width = 7, fig.height = 7} | |
set.seed(100) | |
library("quanteda.textplots") | |
textplot_wordcloud(dfmat_uk, min_count = 6, random_order = FALSE, | |
rotation = .25, | |
color = RColorBrewer::brewer.pal(8, "Dark2")) | |
``` | |
### 変数による文書のグループ化 {#grouping-documents-by-document-variable} | |
**quanteda**では,dfmを作成する際に,文書変数の値によって文書をグループ化するすることができる. | |
```{r} | |
dfmat_ire <- tokens(data_corpus_irishbudget2010, remove_punct = TRUE) %>% | |
tokens_remove(stopwords("en")) %>% | |
tokens_group(groups = party) %>% | |
dfm() | |
``` | |
また、以下のように,dfmを語の頻度順に並べ替えて,中身を確かめられる. | |
```{r} | |
dfm_sort(dfmat_ire)[, 1:10] | |
``` | |
### 辞書による語のグループ化 {#grouping-words-by-dictionary-or-equivalence-class} | |
キーワードがあらかじめ分かっている場合,`dictionary()`によって辞書を作成し、語の出現回数を測定できる。次の例では,テロリズムに関連する言葉や経済に関連する言葉が,クリントン以降の大統領演説でどのように異なるかを示している. | |
```{r} | |
corp_inaug_post1991 <- corpus_subset(data_corpus_inaugural, Year > 1991) | |
``` | |
テロリズムと経済という2つのリストからなる辞書を作成する. | |
```{r} | |
dict <- dictionary(list(terror = c("terrorism", "terrorists", "threat"), | |
economy = c("jobs", "business", "grow", "work"))) | |
``` | |
文書行列を作成するときに,この辞書を`dfm()`の`dictionary`に渡す. | |
```{r} | |
dfmat_inaug_post1991_dict <- dfm(corp_inaug_post1991, dictionary = dict) | |
dfmat_inaug_post1991_dict | |
``` | |
`dictionary()`は,LIWCやWordstatなどの一般的な辞書ファイルを読み込むことができる.以下では,LIWCの辞書を大統領就任演説に適用している. | |
```{r, eval = FALSE} | |
dictliwc <- dictionary(file = "~/Dropbox/QUANTESS/dictionaries/LIWC/LIWC2001_English.dic", | |
format = "LIWC") | |
dfmat_inaug_subset <- dfm(data_corpus_inaugural[52:58], dictionary = dictliwc) | |
dfmat_inaug_subset[, 1:10] | |
``` | |
# 追加の事例 {#further-examples} | |
## 文書の類似性 {#similarities-between-texts} | |
```{r fig.width = 6} | |
dfmat_inaug_post1980 <- dfm(corpus_subset(data_corpus_inaugural, Year > 1980), | |
remove = stopwords("english"), stem = TRUE, remove_punct = TRUE) | |
library("quanteda.textstats") | |
tstat_obama <- textstat_simil(dfmat_inaug_post1980, | |
dfmat_inaug_post1980[c("2009-Obama", "2013-Obama"), ], | |
margin = "documents", method = "cosine") | |
tstat_obama | |
# dotchart(as.list(tstat_obama)$"2009-Obama", xlab = "Cosine similarity") | |
``` | |
上記の文書間の類似性から樹形図を作成して,大統領を階層的に分類することができる. | |
```{r, fig.width = 10, fig.height = 7, eval = TRUE} | |
data_corpus_sotu <- readRDS(url("https://quanteda.org/data/data_corpus_sotu.rds")) | |
dfmat_sotu <- dfm(corpus_subset(data_corpus_sotu, Date > as.Date("1980-01-01")), | |
stem = TRUE, remove_punct = TRUE, | |
remove = stopwords("english")) | |
dfmat_sotu <- dfm_trim(dfmat_sotu, min_termfreq = 5, min_docfreq = 3) | |
# hierarchical clustering - get distances on normalized dfm | |
library("quanteda.textstats") | |
tstat_dist <- textstat_dist(dfm_weight(dfmat_sotu, scheme = "prop")) | |
# hiarchical clustering the distance object | |
pres_cluster <- hclust(as.dist(tstat_dist)) | |
# label with document names | |
pres_cluster$labels <- docnames(dfmat_sotu) | |
# plot as a dendrogram | |
plot(pres_cluster, xlab = "", sub = "", | |
main = "Euclidean Distance on Normalized Token Frequency") | |
``` | |
文書間と同様に用語間の類似性も測定できる. | |
```{r} | |
tstat_sim <- textstat_simil(dfmat_sotu, dfmat_sotu[, c("fair", "health", "terror")], | |
method = "cosine", margin = "features") | |
lapply(as.list(tstat_sim), head, 10) | |
``` | |
## 文書のスケーリング {#scaling-document-positions} | |
**quanteda**には多数のテキスト分析のためのモデルが含まれている.ここでは,ワードフィッシュ(`textmodel_wordfish()`)による教師なしの文書のスケーリングを2010年のアイルランドの予算討論の分析に用いている. | |
```{r} | |
library("quanteda.textmodels") | |
dfmat_ire <- dfm(data_corpus_irishbudget2010) | |
tmod_wf <- textmodel_wordfish(dfmat_ire, dir = c(2, 1)) | |
# plot the Wordfish estimates by party | |
textplot_scale1d(tmod_wf, groups = docvars(dfmat_ire, "party")) | |
``` | |
## トピックモデル {#topic-models} | |
`convert()`を用いると,dfmを**topicmodels**の`LDA()`形式のデータに転換し,簡単にトピックモデルを適用できる. | |
```{r} | |
dfmat_ire2 <- dfm(data_corpus_irishbudget2010, | |
remove_punct = TRUE, remove_numbers = TRUE, remove = stopwords("english")) | |
dfmat_ire2 <- dfm_trim(dfmat_ire2, min_termfreq = 4, max_docfreq = 10) | |
dfmat_ire2 | |
set.seed(100) | |
if (require(topicmodels)) { | |
my_lda_fit20 <- LDA(convert(dfmat_ire2, to = "topicmodels"), k = 20) | |
get_terms(my_lda_fit20, 5) | |
} | |
``` |