コーパス分析専用パッケージの利用

quanteda: Quantitative Analysis of Textual Data

http://sugiura-ken.org/wiki/wiki.cgi/exp?page=quanteda

quantedaの使用例

パッケージのインストール

qunateda 本体

install.packages("quanteda", dependencies=T, repos="http://cran.rstudio.com/")
library(quanteda)
## Warning in stringi::stri_info(): Your native charset is not a superset of US-
## ASCII. This may cause serious problems. Consider switching to UTF-8.

## Warning in stringi::stri_info(): Your native charset is not a superset of US-
## ASCII. This may cause serious problems. Consider switching to UTF-8.
## Package version: 3.1.0
## Unicode version: 13.0
## ICU version: 69.1
## Parallel computing: 12 of 12 threads used.
## See https://quanteda.io for tutorials and examples.

テキストファイルをコーパス分析用のデータとして読み込むreadtextパッケージ

install.packages("readtext", dependencies = T, repos="http://cran.rstudio.com/")
library(readtext)

テキストデータの読み込み

  • タグなどのついていない、テキストデータのみのファイルを、フォルダーにまとめて入れておく。

  • NICERの学習者データについて、テキストのみのファイルに変換する

NICERのCHAT形式のデータをテキスト形式に変換:chatToText.R

https://sugiura-ken.org/wiki/wiki.cgi/exp?page=chatToText

#chatToText
#2020-01-17 sugiura@nagoya-u.jp
#CHATフォーマットのファイルから、
#本文のメインティアのテキストだけを抜き出して
#もとのファイル名に .data を付け足したファイル名で保存する。

chatToText <- function(){
  #ディレクトリー内のすべてのテキストファイルを対象に
  here <- getwd()
  files <- list.files(here, pattern="\\.txt$")
  #読み込むファイル名で、.txt という拡張子でファイル名が終わるものを指定
  for (i in files){
    
    lines.tmp <- scan(i, what="char", sep="\n")
    
    lines.tmp <- scan(i, what="char", sep="\n")
    
    data.tmp <- grep("\\*(JPN|NS)...:\t", lines.tmp, value=T)
    
    body.tmp <- gsub("\\*(JPN|NS)...:\t", "", data.tmp)
    
    body.tmp <- body.tmp[body.tmp != ""]
    
    filename <- i
    filename <- as.factor(filename)
    filename <- paste(filename, ".data", sep="")
    #もとのファイル名に .data という文字列を追加
    #ファイル名の終わりが .txt ではなくなるので再帰的に読み込まれない
    write(body.tmp, file=filename)
    
  }

}

変換実行

setwd("NICER1_3/NICER_NNS")
chatToText()
  • 元データと同じフォルダー内に、拡張子 .data が付いたファイルが生成される。
setwd("NICER1_3/NICER_NNS")
list.files()
  • 元のCHAT形式の .txtファイルと、変換後の .data ファイルの二種類が混在している点に注意。
    • (.data ファイルだけ別のフォルダーに移動しておくのも手。)

readtextパッケージの readtext() を使ってテキストを読み込む

  • 拡張子 .data が付いたファイルだけを読み込むようにする点に注意。
options(warn=-1)
setwd("NICER1_3/NICER_NNS")
nicerJP.data <- readtext("*.data")

コーパス分析用として読み込まれたデータの確認

nicerJP.data
  • doc_id に続いて、本文が text として読み込まれている。

「コーパスデータ化」する: corpus()

nicerJP.corpus <- corpus(nicerJP.data)

nicerJP.corpus
## Corpus consisting of 381 documents.
## JPN501.txt.data :
## "What kind of sports do you like? Do you like soccer, base ba..."
## 
## JPN502.txt.data :
## "Education of "YUTORI" There was the education system that ca..."
## 
## JPN503.txt.data :
## "educational policy What do you think about "yutori kyouiku"?..."
## 
## JPN504.txt.data :
## "The impact of sports You often play sports. In elementary sc..."
## 
## JPN505.txt.data :
## "About sports I want to talk about doing sports. To tell you ..."
## 
## JPN506.txt.data :
## "Is money the most important thing? I often hear that which i..."
## 
## [ reached max_ndoc ... 375 more documents ]

コーパスデータの概要を見る: summary()

summary(nicerJP.corpus)

コーパスデータの中身を見る:as.character

*古いバージョンでは texts() だった

  • そのままコーパスデータ全体を対象として実行すると、すべてのテキストが出力される。
  • 各データが要素として入っているので、要素番号を指定することで個々のファイルデータを見ることができる。
as.character(nicerJP.corpus)[3]
##                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           JPN503.txt.data 
## "educational policy\nWhat do you think about \"yutori kyouiku\"?\nIt is the educational policy started about a decade ago.\nBecause people had been educated based on learning as much knowledge as possible since WWII and they become to luck an ability of thinking by themselves, Japanese government started it to enable Japanese students to study objectively and acquire the ability to live by themselves.\nNowadays, they say this educational policy has much room to improve.\nIt is obvious that as they could learn less knowledge than before, they become not to be able to think and act objectively from the wide and deep prospect.\nSo I am for this critical argument generally.\nBut I think we should not see it as an entirely useless and incorrect policy.\nThen, what should we do?\nI think it is important to analyze what points lead to fail scientifically and acknowledge it precisely.\nFor example, Shortening school time is said to be bad  for students because they are playing video games instead.\nIt is partially true, but when it comes to the children from upper society, actually they get more time to study effectively.\nUnless we argue this problem deeply, we will fail to again."

KWIC検索: kwic(コーパスデータ, “検索文字列”)

kwic(nicerJP.corpus, "however")

文書行列(document-feature matrix)の作成:

dfm()は古くなった

  • 行と列で、テキストごとに単語一覧を作成

    • 行に、文書名(テキストファイル名)
    • 列に、単語が並ぶ
  • どの文書にどの単語が入っているかを統一的に操作(分析)できる

  • 対象は、コーパスデータ

  • オプション

    • stem化: stem=T
      • 語尾変化をなくし「辞書形」にする(機械的にカットするので時々間違える?)
    • 句読点の削除:remove_punct=T
    • 機能語などの頻出語(stopwords)を除く:remove=stopwords(“english”)

かわりに、tokens()とdfm_wordstem()を使うことになった

tokens()

*句読点の削除オプション: remove_punct = T

それに dfm() をかける

tokens_remove(stopwords(“en”))

  • ストップワードの削除
nicerJP.dfm <- dfm(nicerJP.corpus, stem=T, remove_punct=T)

nicerJP.dfm 
## Document-feature matrix of: 381 documents, 3,181 features (96.26% sparse) and 0 docvars.
##                  features
## docs              what kind of sport do you like soccer base ball
##   JPN501.txt.data    1    1  3     6  2  19    2      2    1    1
##   JPN502.txt.data    3    0  7     0  1   2    0      0    0    0
##   JPN503.txt.data    3    0  1     0  2   1    0      0    1    0
##   JPN504.txt.data    0    0  3    17  4  13    0      0    0    0
##   JPN505.txt.data    0    0  8    17 13   5    2      1    0    0
##   JPN506.txt.data    1    0  3     0  3  14    0      0    0    0
## [ reached max_ndoc ... 375 more documents, reached max_nfeat ... 3,171 more features ]
nicerJP.dfm2 <- dfm_wordstem(dfm(tokens(nicerJP.corpus, remove_punct = T)))

nicerJP.dfm2
## Document-feature matrix of: 381 documents, 3,181 features (96.26% sparse) and 0 docvars.
##                  features
## docs              what kind of sport do you like soccer base ball
##   JPN501.txt.data    1    1  3     6  2  19    2      2    1    1
##   JPN502.txt.data    3    0  7     0  1   2    0      0    0    0
##   JPN503.txt.data    3    0  1     0  2   1    0      0    1    0
##   JPN504.txt.data    0    0  3    17  4  13    0      0    0    0
##   JPN505.txt.data    0    0  8    17 13   5    2      1    0    0
##   JPN506.txt.data    1    0  3     0  3  14    0      0    0    0
## [ reached max_ndoc ... 375 more documents, reached max_nfeat ... 3,171 more features ]

文書行列の概要を見る:summary()

summary(nicerJP.dfm)
##  Length   Class    Mode 
## 1211961     dfm      S4
summary(nicerJP.dfm2)
##  Length   Class    Mode 
## 1211961     dfm      S4

文書行列の閲覧:View()

  • Vが大文字なのに注意
View(nicerJP.dfm)

単語頻度一覧: topfeatures()

  • オプションで数字を付けて、何位まで出すか指定できる
topfeatures(nicerJP.dfm)
##    to     i   the   and    is    in    of     a sport    it 
##  3635  3098  2997  2465  2428  2197  2012  1474  1379  1336
topfeatures(nicerJP.dfm2)
##    to     i   the   and    is    in    of     a sport    it 
##  3635  3098  2997  2465  2428  2197  2012  1474  1379  1336

Word Cloudの作成

textplot_wordcloud()は、v3.0より別パッケージになったので、別途インストール必要

install.packages("quanteda.textplots")
library(quanteda.textplots)
textplot_wordcloud(nicerJP.dfm)

textplot_wordcloud(nicerJP.dfm2)

機能語が多くなるので、stopwordを除いたもので作った方が内容がよくわかる

nicerJP.dfm3 <- dfm_wordstem(dfm(tokens_remove(tokens(nicerJP.corpus, remove_punct = T), stopwords("en"))))

textplot_wordcloud(nicerJP.dfm3)

いくつかの単語をまとめてグループにし、そのグループに該当するものの頻度を調べる。

例えば、接続語句のリストのグループを複数作っておいて、それぞれのグループに属する接続語句の頻度をかぞえる。

  • グループを「辞書」と呼ぶ。コマンド名は dictionary()
  • 対象はコーパスデータ
connectives <- dictionary(list(additive = c("moreover", "further", "furthermore"),
                               adversative =  c("however","nevertheless","conversely"),
                               resultative = c("therefore", "thus", "consequently")))

connectives.dfm <- dfm(nicerJP.corpus, dictionary = connectives)

View(connectives.dfm)

連語の頻度と結びつきの強さ:textstat_collocations(コーパスデータ)

quanteda.textstats が別パッケージになった

install.packages("quanteda.textstats")
library(quanteda.textstats)
textstat_collocations(nicerJP.corpus)

オプション

  • 連語の長さ(グラム数)の指定オプション: size = 数字
  • 頻度の最低回数の指定オプション: min_count = 回数

3-gramで、最低限100回以上出現するもの

textstat_collocations(nicerJP.corpus, size = 3, min_count = 100)

連語表現の検索

具体的な連語をベクトルにまとめておく

multiword <- c("in addition", "on the other hand", "as a result")

「フレーズ」という単位で扱われるように指定する

rengo <- phrase(multiword)

kwic検索

kwic(nicerJP.corpus, rengo)
rengo.df <- kwic(nicerJP.corpus, rengo)
write.table(rengo.df, "rengo.df.txt")