這個章節會相對抽象一些。若你只是單純處理「文字資料」,例如選舉資料中的候選人欄位用 character 儲存,就比較不會遇上這個章節遇到的問題。
相反地,若你平常要和文件、語料打交道,那就可能遇到相關情境,例如A單位2022年/2023年的電子書、B單位2021年的電子書等,除了書本以外,還有很多元資料(metadata),就會遇到這個章節標題所說的「文件資料格式」,其實用其他詞可能比文件還精準,但為方便理解還是使用這個詞。
不過,為什麼需要資料框以外的文件資料結構?
使用資料框儲存文件資料確實很方便,因為資料框裡面其他欄位可以方便我們清理資料,例如前面展示過的篩選特定年份、利用stringr
取代特定文字等,全部都能和dplyr
配合進行。然而,在特定情境中,使用專為文件分析設計的資料結構會更為高效和方便,相關考慮因素有記憶體效率、計算效率、針對特定資料結構開發出的功能性、資料本身維度就比較高等。
前面我們介紹tidytext
的時候,就有看到利用資料框(dtaframe)儲存文件資料。再簡單介紹一次,利用資料框儲存文件資料,等同服膺tidy原則,每個列(row)都是一筆資料、一個觀測值(observation),每個行都是一個欄位、一個變數(variable),無論是Excel或者Google Spreadsheet,都是常見的資料框。
因為tidytext
也是在tidyverse
底下運行,所以都會用資料框方式儲存文件資料。
語料(corpus),或稱文集,是一種在老派資料探勘專用套件tm
(text mining簡稱)常見的資料結構。它具備數個特點,包含擴充性高,它可以儲存大規模文件;還有預處理方便,因為有許多內建專門針對語料資料結構的函數,例如大寫轉小寫、去除停用詞、提取詞幹等,不過這點後來其他套件也都做到了;有元數據(metadata)專用儲存結構,例如可以放上作者、出版社(書或者報章雜誌)、出版日期等。
雖然老派,但它還有在更新,你可以造訪tm
官網獲得更多資訊。我沒有很習慣使用它,因為像是stringr
或者quanteda
都有更現代且更加彈性的函數,可以完成相同任務。
library(tm)
texts <- c("I love R.", "R is a language.", "Text mining with R.")
corpus <- Corpus(VectorSource(texts))
corpus <- tm_map(corpus, content_transformer(tolower))
corpus <- tm_map(corpus, removePunctuation)
corpus <- tm_map(corpus, removeNumbers)
corpus <- tm_map(corpus, removeWords, stopwords("en"))
inspect(corpus)
## <<SimpleCorpus>>
## Metadata: corpus specific: 1, document level (indexed): 0
## Content: documents: 3
##
## [1] love r r language text mining r
DTM和DFM概念相似,因此一併介紹。前者全名為文件詞彙矩陣(document term matrix),後者則是文件特徵矩陣(document feature matrix),差別只有 term 和 feature,其實非常相似,term 是指單一詞彙,feature
則是延伸概念,因為開發者認為應該從單一詞彙不夠彈性,所以用特徵或者變數的概念取代詞彙,這個特徵可能是單一詞彙,也可能不是,所以它的概念更上一層。
DTM的每一列代表詞彙、每一行代表文件、每一個值則是詞彙出現頻率(term frequencies),它同樣是tm
中常用的資料結構。DTM則是quanteda
的標準配備,每一列代表不限於詞彙的特徵、每一行代表文件、每一個值則可以是不同類型的數字。
library(tm)
texts <- c("I love R.", "R is a language.", "Text mining with R.")
corpus <- Corpus(VectorSource(texts))
dtm <- DocumentTermMatrix(corpus)
inspect(dtm)
## <<DocumentTermMatrix (documents: 3, terms: 5)>>
## Non-/sparse entries: 5/10
## Sparsity : 67%
## Maximal term length: 9
## Weighting : term frequency (tf)
## Sample :
## Terms
## Docs language. love mining text with
## 1 0 1 0 0 0
## 2 1 0 0 0 0
## 3 0 0 1 1 1
library(quanteda)
texts <- c("我是R語言愛好者", "你喜歡R語言嗎?", "文字探勘有專門的R語言套件")
tokens <- tokens(texts)
dfm <- dfm(tokens)
dfm
## Document-feature matrix of: 3 documents, 15 features (57.78% sparse) and 0 docvars.
## features
## docs 我是 r 語言 愛好者 你 喜歡 嗎 ? 文字 探勘
## text1 1 1 1 1 0 0 0 0 0 0
## text2 0 1 1 0 1 1 1 1 0 0
## text3 0 1 1 0 0 0 0 0 1 1
## [ reached max_nfeat ... 5 more features ]
前面我們談到記憶體效率。當我們有數百萬篇文章需要分析時,使用矩陣儲存資料會更有效率,因為它們採用稀疏矩陣(sparse matrix)結構儲存,只儲存非零元素,從而節省記憶體。什麼意思呢?你可以想像,整理不同篇文章,彼此會有有一些共通出現的詞彙,例如「你」、「我」、「的」、「是」、「和」,但也會有些因文章主題而異的詞彙,例如政治類文章就會有「政黨」和「選舉」、娛樂類文章則會有「音樂」和「表演」。
在此情況下,我們用前面提到的DTM和DFM儲存文章資料,每個文件、每篇文章中,也就是每個列大部分的詞彙出現次數都是0。為什麼?AA文章可能用了250個詞彙、B文章則用了300個詞彙,它們共用的詞彙假設是50個,則我們可以想像,當文章數上升,這個矩陣就會頻繁加上新詞彙,因為共同出現的詞彙就是那些。
當某個矩陣中出現大多數值為0的狀況時,就可以使用專門用來儲存這種資料的稀疏矩陣,它只儲存非零值,以及這些非零值在矩陣中的位置,反正其他都是0。這樣便能大幅減少所需儲存空間,因此增加記憶體儲存效率。
不只是儲存而已,計算效率也能提升。你鐵定在數學課學過矩陣運算,像是線性代數課程就有很多介紹,所以處理矩陣時,既能用項量化運算加速,這會比資料框針對一個一個欄位慢慢處理還快。另外,矩陣也有專門開發的計算方式,例如奇異值分解(SVD),這些都是計算效率上升的展現。
另外,矩陣有專門設計的方法和函數,像是tm
和quanteda
都有開發主題模型與情感分析的專用方法;DTM和DFM也支援高維度文本數據,如果是在資料框裡面,我們就可能要利用unnest
或者其他方式處理,相對沒那麼直觀。這些就是使用資料框以外資料結構的解釋囉!