knitr::opts_chunk$set(collapse = FALSE, comment = "##")
本ページはQuick Start Guideの日本語訳であり,英語のテキスト分析を通じてquantedaの基本的な使い方を説明する.日本語の分析法に関しては,以下のページを参照.
quantedaはCRANからインストールできる.GUIのRパッケージインストーラを使用してインストールするか,次のコマンドを実行する.
install.packages("quanteda")
GitHubから最新の開発バージョンをインストールする方法については,https://github.com/quanteda/quanteda を参照.
quantedaには連携して機能を拡張する一連のパッケージがあり,それらをインストールすることが推奨される.
quanteda.corpora:quantedaの本記事内の説明で使用する追加のテキストデータ
r
devtools::install_github("quanteda/quanteda.corpora")
* LIWCalike: Linguistic Inquiry and Word Count (LIWC) アプローチによるテキスト分析のR実装
r
devtools::install_github("kbenoit/quanteda.dictionaries")
まず,quantedaを読み込んで,パッケージの関数とデータにアクセスできるようにする.
library(quanteda)
quantedaにはテキストを読み込むためのシンプルで強力なパッケージ,readtextがあります.このパッケージのreadtext()
は,ローカス・ストレージやインターネットからファイル読み込み,corpus()
にデータ・フレームを返す.
readtext()
で利用可能なファイルやデータの形式:
.txt
)ファイル.csv
)ファイルquantedaのコーパスを生成する関数である corpus()
は,以下の種類のデータを読み込むことができる.
VCorpus
コーパスオブジェクトコーパスを作成する最も簡単な方法は,corpus()
を用いて,すでにRに読み込まれた文字列ベクトル作成することである.文字列ベクトルをRに取り込む方法はさまざまなので,高度なRユーザーは,コーパスをいろいろな方法で作り出せる.
次の例では,quantedaパッケージに含まれているイギリスの政党が2010年の総選挙のために発行したマニフェストのテキストデータ(data_char_ukimmig2010
)からコーパスを作成している.
corp_uk <- corpus(data_char_ukimmig2010) # テキストからコーパスを作成 summary(corp_uk)
コーパスを作成したあとでも,docvars
を用いると,必要に応じて文書に対応した変数をこのコーパスに追加することができる.
たとえば,Rのnames()
関数を使って文字ベクトル(data_char_ukimmig2010
)の名前を取得し,これを文書変数(docvar()
)に追加することができる.
docvars(corp_uk, "Party") <- names(data_char_ukimmig2010) docvars(corp_uk, "Year") <- 2010 summary(corp_uk)
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)
quantedaのコーパスは,元の文書をユニコード(UTF-8)に変換し,文書に対するメタデータと一緒に格納しすることで、ステミングや句読点の削除などの処理よって変更されないテキストデータの静的な保管庫になるように設計されている.これによって,コーパスから文書を抽出して新しいオブジェクトを作成した後でも,コーパスには元のデータが残り,別の分析を,同じコーパスを用いて行うことができる.
コーパスから文書を取り出すためには,as.character()
と呼ばれる関数を使用する.
as.character(data_corpus_inaugural)[2]
summary()
により,コーパス内のテキストの要約を行うことができる.
data(data_corpus_irishbudget2010, package = "quanteda.textmodels") summary(data_corpus_irishbudget2010)
summary()
の出力をデータ・フレームとして保存し,基本的な記述統計を描画することができる.
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), ]
+
演算子を用いると,簡単に二個のコーパスを連結できます.コーパスが異なる構造を持つ場合でも,文書変数が失われることはなく,コーパスのメタデータも引き継がれる.
library(quanteda) corp1 <- corpus(data_corpus_inaugural[1:5]) corp2 <- corpus(data_corpus_inaugural[53:58]) corp3 <- corp1 + corp2 summary(corp3)
corpus_subset()
により,文書変数に適用される論理条件に基づいて文書を抽出することができる.
summary(corpus_subset(data_corpus_inaugural, Year > 1990)) summary(corpus_subset(data_corpus_inaugural, President == "Adams"))
kwic()
(keywords-in-context)は単語の検索を行い,その単語が現れる文脈を表示する.
toks <- tokens(data_corpus_inaugural) kwic(toks, pattern = "terror")
kwic(toks, pattern = "terror", valuetype = "regex")
kwic(toks, pattern = "communist*")
上記の要約では,"Year"と"President"は各文書に結び付けられた変数であり,docvars()
によってそれらにアクセスできる.
head(docvars(data_corpus_inaugural))
quanteda.corporaをインストールすることで,より多くのコーパスを試すことができる.
文書のスケーリングなどの統計分析を行うためには,それぞれの文書の特長をまとめた行列を作成する必要があり,quantedaでは,このような行列を生成するために dfm()
を使いる. dfmはdocument-feature matrixの略で,行が文書(document),列が特長(feature)となる行列である.行と列をこのように定義する理由は,データ分析では行が分析単位になり,各列が分析対象になる変数となるのが一般的だからである.多くのソフトウェアでは,この行列をdocument-term matrixと呼ぶが,quantedaが語(term)でなはく特長(feature)という用語を使うのは,特長のほうが一般性を持つからで,テキスト分析では,単語,語幹,単語の集合,Nグラム,品詞など様々なものが文書の特長となる.
テキストを簡単にトークン化するために,quantedaは tokens()
と呼ばれる強力なコマンドを提供する.この関数は,文字ベクトルのトークンのリストからなるオブジェクトを生成する.このオブジェクトでは,リストの一つ一つの要素は入力された文書に対応している.
tokens()
は保守的に設計されており、ユーザーが明示的に指示を与えないかぎりは,要素を削除しない.
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()
には個々の文字をトークン化するオプションもある.
tokens("Great website: http://textasdata.com?page=123.", what = "character") tokens("Great website: http://textasdata.com?page=123.", what = "character", remove_separators = FALSE)
もしくは,一文ごとにトークン化するオプションもある.
# 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")
データからすぐに文書行列を作成したい場合は、dfm()
に直接文字列ベクトルもしくはコーパスを渡すと、自動的にトークン化が行われ。dfm()
は、デフォルトで大文字から小文字への置換や,句読点を除去などの操作を適用する.また,dfm()
からtokens()
の全てのオプションを利用できる.
corp_inaug_post1990 <- corpus_subset(data_corpus_inaugural, Year > 1990) # make a dfm dfmat_inaug_post1990 <- dfm(tokens(corp_inaug_post1990)) dfmat_inaug_post1990[, 1:5]
以下の例ではdfm()
の追加のオプションを用いて、ストップワードの削除(remove
)と語のステミング(stem
)を行っている.
# make a dfm, removing stopwords and applying stemming dfmat_inaug_post1990 <- tokens(corp_inaug_post1990, remove_punct = TRUE) |> tokens_remove(stopwords("english")) |> tokens_wordstem() |> dfm() dfmat_inaug_post1990[, 1:5]
remove
によって,文書行列から除外するトークンを指定する.stopwords()
は,幾つかの言語で定義されたストップワードのリストを返す.
head(stopwords("en"), 20) head(stopwords("ru"), 10) head(stopwords("ar", source = "misc"), 10)
RStudioの"Environment"パネル,またはRのView()
を用いることで,dfmに格納された値を見ることができる.
dfmat_uk <- data_char_ukimmig2010 |> tokens(remove_punct = TRUE) |> tokens_remove(stopwords("english")) |> dfm() dfmat_uk
頻度が最も高い特長を見るには,topfeatures()
を用いる.
topfeatures(dfmat_uk, 20) # 20 most frequent words
dfmをtextplot_wordcloud()
に渡すことで,ワードクラウドを描画できる.この関数は,オブジェクトや引数をwordcloudパッケージのwordcloud()
に渡すので,ワードクラウドの表示を変更できる.
set.seed(100) library("quanteda.textplots") textplot_wordcloud(dfmat_uk, min_count = 6, random_order = FALSE, rotation = .25, color = RColorBrewer::brewer.pal(8, "Dark2"))
quantedaでは,dfmを作成する際に,文書変数の値によって文書をグループ化するすることができる.
dfmat_ire <- tokens(data_corpus_irishbudget2010, remove_punct = TRUE) |> tokens_remove(stopwords("en")) |> tokens_group(groups = party) |> dfm()
また、以下のように,dfmを語の頻度順に並べ替えて,中身を確かめられる.
dfm_sort(dfmat_ire)[, 1:10]
キーワードがあらかじめ分かっている場合,dictionary()
によって辞書を作成し、語の出現回数を測定できる。次の例では,テロリズムに関連する言葉や経済に関連する言葉が,クリントン以降の大統領演説でどのように異なるかを示している.
corp_inaug_post1991 <- corpus_subset(data_corpus_inaugural, Year > 1991)
テロリズムと経済という2つのリストからなる辞書を作成する.
dict <- dictionary(list(terror = c("terrorism", "terrorists", "threat"), economy = c("jobs", "business", "grow", "work")))
文書行列を作成するときに,この辞書をdfm()
のdictionary
に渡す.
dfmat_inaug_post1991_dict <- tokens(corp_inaug_post1991) |> tokens_lookup(dict) |> dfm() dfmat_inaug_post1991_dict
dictionary()
は,LIWCやWordstatなどの一般的な辞書ファイルを読み込むことができる.以下では,LIWCの辞書を大統領就任演説に適用している.
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]
dfmat_inaug_post1980 <- data_corpus_inaugural |> corpus_subset(Year > 1980) |> tokens(remove_punct = TRUE) |> tokens_remove(stopwords("english")) |> tokens_wordstem() |> dfm() 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")
上記の文書間の類似性から樹形図を作成して,大統領を階層的に分類することができる.
data_corpus_sotu <- readRDS(url("https://quanteda.org/data/data_corpus_sotu.rds")) dfmat_sotu <- data_corpus_sotu |> corpus_subset(Date > as.Date("1980-01-01")) |> tokens(remove_punct = TRUE) |> tokens_remove(stopwords("english")) |> tokens_wordstem() |> dfm() 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")
文書間と同様に用語間の類似性も測定できる.
tstat_sim <- textstat_simil(dfmat_sotu, dfmat_sotu[, c("fair", "health", "terror")], method = "cosine", margin = "features") lapply(as.list(tstat_sim), head, 10)
quantedaには多数のテキスト分析のためのモデルが含まれている.ここでは,ワードフィッシュ(textmodel_wordfish()
)による教師なしの文書のスケーリングを2010年のアイルランドの予算討論の分析に用いている.
library("quanteda.textmodels") dfmat_ire <- dfm(tokens(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"))
convert()
を用いると,dfmをtopicmodelsのLDA()
形式のデータに転換し,簡単にトピックモデルを適用できる.
dfmat_ire2 <- data_corpus_irishbudget2010 |> tokens(remove_punct = TRUE, remove_numbers = TRUE) |> tokens_remove(stopwords("english")) |> tokens_wordstem() |> dfm() 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) }
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.