2.1 实用意义上的文本挖掘
文本挖掘是指采用大量非结构化语言并快速提取可能影响利益相关者决策的有用且新颖的见解的能力。(视文本挖掘为手段)
❓文本挖掘适合使用传统的ML工作流程吗?
传统上,机器学习工作流程分为三个部分。 输入历史数据,然后是建模方法,最后是对新观测值的预测结果进行评价。
文本挖掘过程很好地映射到了机器学习工作流程的三个主要部分。
- 文本挖掘也需要历史数据,从中可以得出新的结果或预测。 在文本的情况下,训练数据称为语料库或语料库。 此外,在机器学习和文本挖掘中,都需要识别和组织数据源。
- 与传统的ML算法相比,文本挖掘分析可以包含非算法推理,如简单的词频统计,更偏向于探索性数据分析。尽管如此,文本挖掘也可以采用算法建模。
2.2 文本挖掘类型——词袋
总的来说,有两种类型的文本挖掘,一种叫做“单词袋”,另一种是“语法分析”,各有优缺点。 单词方法易于理解和分析,甚至可以进行机器学习。
Bag of words将每个单词或词组(n-gram)视为文本的独特特征,不考虑词序和单词语法。
文档词项矩阵DTM,每一行代表一个文档/单个语料;
2.2.1 句法分析
它基于单词语法。 语法从根本上代表了一组规则,这些规则定义了句子的组成部分,然后将这些组成部分组合起来构成句子本身。
R中的OpenNLP包可以进行句法分析,如词性标注。
2.3 R语言字符串操作
案例:https://github.com/kwartler/text_mining
下载数据 oct_delta.csv
https://cbail.github.io/textasdata/basic-text-analysis/rmarkdown/Basic_Text_Analysis_in_R.htmlcbail.github.io
函数:paste,paste0,grep,grepl,gsub
包:stringr,stringi
options(stringsAsFactors=F) #避免字符串自动转化为因子类型
```{r,warning=FALSE}
setwd("E:/Rdata/text_mining-master/")
options(stringsAsFactors = FALSE)
library(stringr)
library(stringi)
library(qdap)
```
```{r}
setwd("E:/Rdata/text_mining-master/")
text.df<-read.csv('oct_delta.csv')
attach(text.df)
head(text)
```
### nchar
```{r}
nchar(c("abc","cd","hello world"))
#1.推文的平均字数
mean(nchar(text,type="bytes"))
#2.仅保留非空文档
subset.doc<-subset(text,nchar(text,type ="bytes")>0)
```
### sub
```{r,warning=TRUE}
#1.将thanks全部替换成thank you
sub('thanks','thank you',text,ignore.case = TRUE)[1]
#2.将1-3行中的pls替换为please
text[1:3]
sub('pls','please',text[1:3],ignore.case = F)
```
ignore.case是否区分大小写
### gsub
```{r}
#gsub可以多次匹配替换
fake.text<-'R text mining is good but text mining in Python is also'
gsub('text mining','tm',fake.text,ignore.case = F)
sub('text mining','tm',fake.text,ignore.case = F)
#gsub可以用于去掉特殊字符
text[5]
gsub('&','',text[5])
text[1:3]
gsub('[[:punct:]]','',text[1:3])
```
### mgsub
```{r,warning=FALSE}
library(qdap)
patterns<-c('good','also','text mining')
replacements<-c('great','just as suitable','tm')
fake.text
mgsub(patterns,replacements,fake.text)
```
注意:小心使用gsub!
如将RT转化为空格,删除转推,可能会导致airport变成airpo。
### paste
```{r}
text.df$combined<-paste(month,date,year,sep='-')
head(text.df$combined)
```
```{r}
library(lubridate)
text.df$combined<-mdy(text.df$combined)
class(text.df$combined)
```
### strsplit
```{r}
agents<-strsplit(text,'[*]')
agents[1:3]
```
### substring
```{r}
substring('R text mining is great',18,22)
```
### last.chars
```{r}
#获取最后长度weinum的字符串
last.chars<-function(text,num){
len=nchar(text,type="bytes")
last<-substring(text,len-num+1,len)
return(last)
}
last.chars('R text mining is good',4)
last.chars(text[1:2],2)
```
```{r}
#查看工作日各个代理的推文数量
weekdays<-subset(text.df,
combined>=mdy('10-05-2015')&
combined<=mdy('10-09-2015'))
agents<-last.chars(weekdays$text,2)
table(agents)
```
2.4 搜索 关键字
### grep
类似于unix系统的grep函数
```{r}
#检索所有出现sorry的位置
grep("sorry",text[1:80],ignore.case = T)
grepl("sorry",text[1:80],ignore.case = T) #布尔值
grep(c("sorry|apologize"),text[1:80],ignore.case = T)
```
```{r}
sum(grepl('[0-9]{3}|[0-9]{4}',text))/length(text)
sum(grepl('http',text,ignore.case = T))/length(text)
```
2.5 stringr和stringi
### stringi
```{r}
library(stringi)
#快速判断是否存在http,返回0-1值
sum(stri_count(text,fixed = "http"))
```
### stringr
```{r}
library(stringr)
sum(str_detect(text,'http')) #返回布尔值
```
```{r}
patterns<-with(text.df,str_detect(text,'http')&
str_detect(text,'[0-9]{3}-'))
text[patterns]
```
2.6 词袋文本挖掘的预处理
tm包中的重要函数
注:全部转化为小写会影响命名实体识别,专有名词;删除数字会影响金额数据的提取。
tm包提供了常用停用词列表,可以根据实际问题添加或减少单词。例如:在挖掘法律文档时,需要通过添加“原告”,“被告”之类的词来自定义停用词表。
```{r,warning=FALSE}
library(tm)
tweets<-data.frame(ID=seq(1:nrow(text.df)),text=text.df$text)
#文本预处理
#1.转化为小写
tryTolower<-function(x){
y=NA
#异常处理
try_error=tryCatch(tolower(x),
error=function(e)e)
if(!inherits(try_error,'error'))
y=tolower(x)
return(y)
}
#2.定义停用词
custom.stopwords<-c(
stopwords('english'),'lol','smh','delta'
)
```
```{r,warning=FALSE}
#3.整理语料
clean.corpus<-function(corpus){
corpus<-tm_map(corpus,content_transformer(tryTolower)) #转化为小写
corpus<-tm_map(corpus,removeWords,custom.stopwords)
#去停用词
corpus<-tm_map(corpus,removePunctuation)
corpus<-tm_map(corpus,stripWhitespace) #去掉多余的空格
corpus<-tm_map(corpus,removeNumbers) #去掉数值
return(corpus)
}
```
```{r}
#4.生成语料库
require(devtools)
#install_version("tm",version="0.7-1") #注意tm包的版本
library(tm)
m<-list(id='ID',content='text')
myReader=readTabular(m)
corpus<-VCorpus(DataframeSource(tweets),readerControl=list(reader=myReader))
#VCorpus是存储在内存中的而PCorpus则创建永久语料库
corpus<-clean.corpus(corpus)
as.list(corpus)[1] #查看第一条推文
as.character(corpus[[1]])
```
2.7 错误拼写检查
library(qdap) tm.definition<-'Txt mining is the process of distilling actionable insyghts from text.'
ck=check_spelling(tm.definition)
#check_spelling(x)函数的方法
```{r}
#拼写检查
library(tm)
library(qdap)
tm.definition<-'Txt mining is the process of distilling actionable insyghts from text.'
which_misspelled(tm.definition)
#交互式改错
check_spelling_interactive(tm.definition)
```
```{r}
fit.text<-function(myStr){
check<-check_spelling(myStr)
#将字符串按空格切分,生成列表
splitted<-strsplit(myStr,split=" ")
for(i in 1:length(check$row)){
splitted[[check$row[i]]][as.numeric(check$word.no[i])]=
check$suggestion[i]
}
#将切分词后的列表转化为字符串
df<-unlist(lapply(splitted,function(x) paste(x,collapse = ' ')))
return(df)
}
fit.text(tm.definition)
```
文档词频矩阵 DTM
#TDM
tdm<-TermDocumentMatrix(corpus,control=list(weighting=weightTf))
tdm.tweets.m<-as.matrix(tdm)
tdm.tweets.m[2250:2255,1340:1342]
```{r}
#TDM
tdm<-TermDocumentMatrix(corpus,control=list(weighting=weightTf))
class(tdm)
tdm.tweets.m<-as.matrix(tdm)
tdm.tweets.m[2250:2255,1340:1342]
term.freq=rowSums(tdm.tweets.m) #每个单词的词频
freq.df<-data.frame(word=names(term.freq),
frequency=term.freq)
#按词频降序排列
head(freq.df[order(freq.df[,2],decreasing = T),])
```