本文涉及尖殃,使用R語言讀取文本(從txt文件、http鏈接或是https鏈接)划煮,構(gòu)建TermDocumentMatrix(統(tǒng)計每個term(單詞或詞組)在每個document中出現(xiàn)的頻次)送丰,繪制wordcloud,并進行情感分析(Sentiment Analysis)弛秋。
關(guān)鍵字: R語言器躏,文本挖掘俐载,WordCloud,Sentiment Analysis
數(shù)據(jù)來源:
要挖掘的數(shù)據(jù)來自于:
美國布什總統(tǒng)出兵伊拉克前的演講:
https://www.historyplace.com/speeches/bush-war.htm
positive words和negative words來自于:
https://www.cs.uic.edu/~liub/FBS/sentiment-analysis.html
1 文本讀取
1.1 從文件中讀取文本
使用如下方法讀取文本數(shù)據(jù)(scan或者readLines)
setwd("E:/Project/tripping/R_Plot/Data")
textfile <- "GB.txt"
# 一行一行地讀取文本數(shù)據(jù)
# 方法1:
text <- scan(textfile, character(0), sep='\n')
#方法2: text <- readLines(textfile)
就我實驗結(jié)果來看登失,讀取的結(jié)果是一樣的遏佣,都是把一行字符串作為列表中的一個元素.
1.2 從網(wǎng)頁中讀取文本
使用如下代碼從一個HTTP鏈接中讀取文本,讀取的結(jié)果與1.1相同(這里我把一個模塊用if語句括起來了揽浙,是為了方便注釋)
# --- 從網(wǎng)頁讀取文本
library(XML) # 應(yīng)注意XML不支持HTTPS協(xié)議状婶,HTTPS應(yīng)先用RCurl中的getURL載入數(shù)據(jù),或直接把HTTPS改為HTTP
# 處理HTTP
if (FALSE) {
textLocation <- URLencode("http://www.historyplace.com/speeches/bush-war.htm")
doc.html <- htmlTreeParse(textLocation, useInternal=TRUE)
text <- unlist(xpathApply(doc.html, '//p', xmlValue))
head(text, 3)
}
但要注意馅巷,HTTPS鏈接不適用于上面的xml方法太抓,對于HTTPS,要么把鏈接里的HTTPS改成HTTP令杈,然后用上面的xml方法走敌,或者采用下面的RCurl的方法:
# 如果處理的是HTTPS,可如下處理:
if (TRUE) {
library(RCurl)
url <- "http://www.reibang.com/p/48d758ce62b4"
web <- getURL(url)
doc<-htmlTreeParse(web,encoding="UTF-8", error=function(...){}, useInternalNodes = TRUE,trim=TRUE)
text <- unlist(xpathApply(doc, '//p', xmlValue))
head(text, 3) # 在text中逗噩,每個元素是一行字符串
}
2 繪制WordCloud
剛剛讀取的文本數(shù)據(jù)掉丽,形成的是一個列表,列表里每個元素是一個字符串异雁,代表文本中的一行捶障。
接下來我們要繪制WordCloud,需要統(tǒng)計在整個文本中每個單詞出現(xiàn)的次數(shù)纲刀,然后對于高頻詞的單詞畫的更大项炼。
我們采用的方式是,先構(gòu)建一個矩陣示绊,其中第i行第j列的元素表示第i個單詞在文本的第j行中出現(xiàn)的次數(shù)锭部。
library("tm")
words.vec <- VectorSource(text)
words.corpus <- Corpus(words.vec)
# 第二個參數(shù)里的content_transformer貌似加不加都一樣的,這里對數(shù)據(jù)進行預(yù)處理
words.corpus <- tm_map(words.corpus, content_transformer(tolower))
words.corpus <- tm_map(words.corpus, content_transformer(removePunctuation))
words.corpus <- tm_map(words.corpus, removeNumbers)
words.corpus <- tm_map(words.corpus, removeWords, stopwords("english")) # 刪除stop words
tdm <- TermDocumentMatrix(words.corpus)
tdm
最后的tdm就是我們想要的矩陣,我們在輸入tdm后面褐,可以看到關(guān)于它的統(tǒng)計信息:
# 輸出解讀:
<<TermDocumentMatrix (terms: 578, documents: 37)>> #一共有578個term拌禾,37個documents(37行)
Non-/sparse entries: 934/20452 #在term-documents構(gòu)成的578*37矩陣中,非空的只有934個元素
Sparsity : 96% #有96%的元素是空值
Maximal term length: 16 #一個term并非是一個單詞展哭,可能是一個詞組湃窍,這里是最大term長度(16個字母)
Weighting : term frequency (tf)
接下來,我們只需要對每一行求和匪傍,即可得到每個單詞在整個文本中出現(xiàn)的頻次:
m <- as.matrix(tdm)
wordCounts <- rowSums(m)
wordCounts <- sort(wordCounts, decreasing = TRUE)
head(wordCounts)
這里的wordCounts即為所求您市,接下來,我們把wordCounts轉(zhuǎn)化成DataFrame的格式役衡,便于繪制WordCloud
cloudFrame <- data.frame(word=names(wordCounts), freq=wordCounts)
# -- 繪制wordcloud
library("wordcloud")
wordcloud(cloudFrame$word, cloudFrame$freq)
繪制的WordCloud如下圖所示:
3 情感分析(Sentiment Analysis)
在情感分析中茵休,我們的目標是分析這個文本是積極的(positive)還是消極的(negative)
在之前已經(jīng)有一些研究收集了英語中的積極詞匯和消極詞匯:
https://www.cs.uic.edu/~liub/FBS/sentiment-analysis.html
我們只需要統(tǒng)計我們的目標文本中積極詞匯所占的比例和消極詞匯所占的比例,即可得到關(guān)于文本的積極評分和消極評分。
首先泽篮,讀取積極詞匯文件和消極詞匯文件,和剛剛一樣柑船,這里我們也是按行讀取的帽撑,不過在這兩個文件里,每個單詞一行鞍时,所以這樣也沒什么問題亏拉。要注意,文本的開頭有些別的信息逆巍,要刪掉及塘。
# -- Sentiment Analysis
setwd("../Data/opinion-lexicon-English")
pos <- "positive-words.txt"
neg <- "negative-words.txt"
p <- scan(pos, character(0), sep="\n")
n <- scan(neg, character(0), sep="\n")
p <- p[-1:-29] # 文件的開頭有些別的東西,要去掉
n <- n[-1:-30]
head(p, 10)
head(n, 10)
讀取了積極單詞和消極單詞后锐极,我們首先統(tǒng)計文本中積極單詞的個數(shù):
totalWords <- sum(wordCounts) # 總的單詞數(shù)目
words <- names(wordCounts) # 都有哪些單詞
matched <- match(words, p, nomatch=0) # 返回一個矩陣笙僚,表示words中的每一個單詞是p中的第幾個單詞
mCounts <- wordCounts[which(matched != 0)]
length(mCounts) # 這篇文章中出現(xiàn)的positive的單詞的種類個數(shù)(there were 40 unique positive words)
nPos <- sum(mCounts)
nPos # 共有58個positive words
然后用同樣的方法統(tǒng)計消極單詞的個數(shù):
# -- 下面對negative words做同樣的操作,統(tǒng)計unique negative words的個數(shù)和negative words的個數(shù)
matched <- match(words, n, nomatch = 0)
nCounts <- wordCounts[which(matched != 0)]
nNeg <- sum(nCounts)
length(nCounts)
nNeg
最后分別計算積極單詞和消極單詞所占的比率:
totalWords <- length(words)
ratioPos <- nPos / totalWords
ratioNeg <- nNeg / totalWords
ratioPos
ratioNeg
最后結(jié)果:
> ratioPos
0.100346
> ratioNeg
0.1020761