用R语言一步步实现文本挖掘教程
中文及英文的文本挖掘——R语言
所需要的包tm(text mining) rJava,Snowball,zoo,XML,slam,Rz, RWeka,matlab
1 文本挖掘概要
文本挖掘是从大量的文本数据中抽取隐含的,求和的,可能有用的信息。
通过文本挖掘实现
•Associate:关联分析,根据同时出现的频率找出关联规则
•Cluster:将相似的文档(词条)进行聚类
•Categorize:将文本划分到预先定义的类别里
•文档自动摘要:利用计算机自动地从原始文档中提取全面准确地反映该文档中心内容的简单连贯描述性短文。
文本挖掘的运用主要有如下几方面
l 智能信息检索
同义词,简称词,异形词,同音字、赘字移除
l 网络内容安全
内容监控
内容过滤
l 内容管理
自动分类
检测和追踪
l 市场监测
口碑监测
竞争情报系统
市场分析
2 英文文本挖掘实例
实现多个英文文档的聚类分析
2.1 文本预处理
2.1.1 读取文本内容
#取得tm内部文件texts/crude/下的文件目录。
>library("tm",lib.loc="d:/ProgramFiles/R/R-3.0.3/library") > vignette("tm")#获取相关帮助文档的内容,pdf格式 reut<-system.file("texts","crude",package='tm')
# 用Corpus命令读取文本并生成语料库文件由于要读取的是xml文件,所以需要xml包 reuters <- Corpus(DirSource(reut), readerControl = list(reader = readReut21578XML)) # DirSource指示的是文件夹路径,如果是单个向量要设为语料库则VectorSource(向量名) readerControl不用设置
查看前两个语料变量内容
另外可以从本地文件中读取用户txt文件
> inputtest<-read.csv(file.choose())
2.1.2 文本清理
对于xml格式的文档用tm_map命令对语料库文件进行预处理,将其转为纯文本并去除多余空格,转换小写,去除常用词汇、合并异形同意词汇,如此才能得到类似txt文件的效果
需要用到的包SnowballC
reuters <- tm_map(reuters, PlainTextDocument)#去除标签
reuters <- tm_map(reuters, stripWhitespace)#去多余空白
reuters <- tm_map(reuters, tolower)#转换小写
reuters <- tm_map(reuters, removeWords, stopwords("english"))
tm_map(reuters, stemDocument)
2.1.3 查找含有特定语句的文档
例如找出文档编号为237而且包含句子INDONESIA SEEN AT CROSSROADS OVER ECONOMIC CHANGE的文档。
> query <- "id == '237' & heading == 'INDONESIA SEEN AT CROSSROADS OVER ECONOMIC CHANGE'"
> tm_filter(reuters, FUN = sFilter, query)
找到
由于语料库已经将大小写转换以及将介词类删除所以对应的语句只是特有单词的组合。
2.1.4 生成词频矩阵并查看内容
dtm <- DocumentTermMatrix(reuters)
查看某部分的词频内容个数,其中dtm行提示哪个文件,列表示词语。
> inspect(dtm[10:15,110:120])
A document-term matrix (6 documents, 11 terms)
Non-/sparse entries: 6/60
Sparsity : 91%
Maximal term length: 9
Weighting : term frequency (tf)
Terms
Docs activity. add added added. address addressed adherence adhering advantage advisers agency
[1,] 0 0 0 0 0 0 1 1 0 0 2
[2,] 0 0 0 0 0 0 0 0 0 0 0
[3,] 0 0 0 0 0 0 0 0 0 0 1
[4,] 0 0 0 0 0 0 0 1 0 0 2
[5,] 0 0 0 0 0 0 0 0 0 0 0
[6,] 0 0 0 0 0 0 0 0 0 0 0
2.1.5 查看含有特定词的文档
若要考察多个文档特定词汇的出现频率或以手工生成字典,并将其作为生成阵的参数
> inspect(tdm[c("price", "texas"),c("127","144","191","194")])
A term-document matrix (2 terms, 4 documents)
Non-/sparse entries: 6/2
Sparsity : 25%
Maximal term length: 5
Weighting : term frequency (tf)
Docs
Terms 127 144 191 194
price 2 1 2 2
texas 1 0 0 2
> inspect(DocumentTermMatrix(reuters, + list(dictionary = c("prices", "crude", "oil"))))
A document-term matrix (20 documents, 3 terms)
Non-/sparse entries: 41/19
Sparsity : 32%
Maximal term length: 6
Weighting : term frequency (tf)
Terms
Docs crude oil prices
127 3 5 4
144 0 11 4
191 3 2 0
194 4 1 0
211 0 2 0
236 1 7 2
237 0 3 0
2.1.6 元数据操作(词元素)
2.1.6.1 查看词条出现次数大于某个具体值的词
findFreqTerms(dtm,5)#查看出现频大于等于5的词
2.1.6.2 查看与某一词相关度大于0.8的词条
> findAssocs(dtm,'opec',0.8)
opec
meeting 0.88
15.8 0.85
oil 0.85
emergency 0.83
analysts 0.82
buyers 0.80
2.1.7 处理词频矩阵
> dtm2<-removeSparseTerms(dtm,sparse=0.95) //parse值越少,最后保留的term数量就越少0.95是指如果某一词出现在文档的概率少于(1-0.95)则不再保留到词频矩阵。即删除权重少的元素。
2.1.8 转换为标准阵
temp=as.data.frame(inspect(dtm2))
> temptoscale<-scale(temp)
2.2 文本挖掘——聚类分析
> d <- dist(temptoscale, method = "euclidean") > fit <- hclust(d, method="ward") > plot(fit)
2.3 分析结果
从聚类图可以看出,文档16和17是比较接近的。而3,4,1,19可以聚成一类,1,6,11,10,13也可分别聚为一类
3 中文文本挖掘实例
3.1 前期准备
3.1.1 Mmseg4j分词
使用中文分词法,由于词之间无有像英文一样的空隔,好在有Java已经解决了这样的问题,我们只需要在R-console里加载rJava与rmmseg4j两个工具包即可。如
>mmseg4j("中国人民从此站起来了")
[1] 中国 人民 从此 站 起来
但事实上其技术是好几代之前的了,目前很少有人还在使用,并且其精度不高,用户自定义词典在R测试并无效。
> teststring<-c('我要学习r语言,兴趣小组,学无止尽') > mmseg4j(teststring)
[1] "我要 学习 r 语言 兴趣小组 学 无止 尽"
尽管在D:\Program Files\R\R-3.0.3\library\rmmseg4j\userDic中将自定义的词典r语言写入,但似乎并没有被识别到。
3.1.2 Rwordseg介绍
所需要的中文分词包Rwordseg,rjava包
Rwordseg 是一个R环境下的中文分词工具,使用rJava调用Java分词工具Ansj。
Ansj 也是一个开源的 Java 中文分词工具,基于中科院的 ictclas 中文分词算法,采用隐马尔科夫模型(Hidden Markov Model, HMM)。作者孙健重写了一个Java版本,并且全部开源,使得 Ansi 可用于人名识别、地名识别、组织机构名识别、多级词性标注、关键词提取、指纹提取等领域,支持行业词典、 用户自定义词典。
3.1.2.1 分词
segmentCN(strwords,
analyzer = get("Analyzer", envir = .RwordsegEnv),
nature = FALSE, nosymbol = TRUE,
returnType = c("vector", "tm"), isfast = FALSE,
outfile = "", blocklines = 1000)
nature用于设置是否输出词性,默认不用。
> segmentCN(teststring)
[1] "我" "要" "学习" "r语言" "兴趣" "小组" "学" "无" "止" "尽"
加入用户自定义词典并进行测试
3.1.2.2 自定义词典
> insertWords(c("我要")) > segmentCN(teststring)
[1] "我要" "学习" "r语言" "兴趣" "小组" "学" "无" "止" "尽"
3.1.2.3 安装新的词典
installDict("E:/default.dic")
3.1.2.4 人名识别设置
> getOption("isNameRecognition")
[1] FALSE
segment.options(isNameRecognition = TRUE)用于设置是否进行人名识别
segment.options(isNameRecognition = TRUE)
3.1.3 读取网站内容
> library("XML", lib.loc="d:/Program Files/R/R-3.0.3/library") > x <- htmlParse("http://cos.name/cn/") > iconv(xmlValue(getNodeSet(x, "//a[@href]")[[1]]), 'UTF-8', '')#转换编码
[1] "COS论坛 | 统计之都"
tables=readHTMLTable(x)#读取内容
> tables
$`NULL`
NULL
$latest
帖子 — 发表新帖子 <U+00BB> 回复 作者 最后回复 最近更新
1 COS论坛说明(新手必读) – 23…474849 979 谢益辉 cassiusoat 2 周
3.1.4 Tm中文常识
在tm 中主要的管理文件的结构被称为语料库(Corpus),代表了一系列的文档集合。语料库是一个概要性的概念,在这里分为动态语料库(Volatile Corpus,作为R 对象保存在内存中)和静态语料库(Permanent Corpus,R 外部保存)。在语料库构成中,x 必须有一个说明资料来源(input location)的源对象(Source Object)。我们可以看一下tm 中Corpus(或VCorpus)函数的用法,对于动态语料库:
Corpus(x,
2 readerControl = list(reader = x$DefaultReader, language = "en"),
3 …)
在tm 中静态语料库也是可以处理的,但需要使用filehash 包来支持:
1 PCorpus(x,
2 readerControl = list(reader = x$DefaultReader, language = "en"),
3 dbControl = list(dbName = "", dbType = "DB1"),
4 …)
对于这些资料来源(即x),tm 包提供了一些相关的函数,比如
• DirSource:处理目录
• VectorSource:由文档构成的向量
• DataframeSource:数据框,就像CSV 文件
第二个参数是readerControl,这里必须声明reader 和language 两个内容。第一个reader是指从资料源创立的文本文件。tm 包提供了一系列的函数支持(比如,readPlain(),readGmane(), readRCV1(), readReut21578XMLasPlain(), readPDF(), readDOC() 等)。
3.2 文件整理
将各个文档放入一个csv文件夹中,格式如下
3.3 读取文件
> mydata<-read.csv(file.choose(),header=T)
3.4 生成并处理语料库
> txt<-Corpus(VectorSource(mydata)) > txt<-tm_map(txt,removeNumbers)#去除数字 > txt<-tm_map(txt,stripWhitespace)#去除多余空格 > txt<-tm_map(txt,removePunctuation)#去除标点符号 > txt<-tm_map(txt,removeWords, stopwords("english"))#将英文中的停词删掉:例如把that at 等英文介词去掉。 > txt<-tm_map(txt,PlainTextDocument)#去掉空文件 > inspect(txt[1])#查看内容
A corpus with 1 text document
The metadata consists of 2 tag-value pairs and a data frame
Available tags are:
create_date creator
Available variables in the data frame are:
MetaID
$txt1
确定性趋势
3.5 中文分词并重新生成语料库
txt<-segmentCN(as.character(txt))#将语料库中的中文时行分词
txt<-Corpus(VectorSource(txt))
3.6 导入中文停词表
将文件转换成csv文件导入中文停词表,并转换成向量格式
cnword<-read.csv(file.choose(),header=F,stringsAsFactors=F) cnword<-as.vector(cnword[1:dim(cnword)[1],])#需要为向量格式
3.7 生成词频矩阵并处理稀疏词汇
dtm<-DocumentTermMatrix(txt,control=list(dictionary=cnword,removePunctuation = TRUE,stopwords=TRUE, wordLengths = c(1, Inf))) # Punctuation是否去掉标点符号默认falseremoveNumbers是否去掉数字默认false,#dictionary设置要统计的中文词语,如果不设置的话,默认会从所有的语料库里统计。#wordLengths设置如果词的长度大于X时舍去。 > dtm2 = removeSparseTerms(dtm, sparse=0.9) df_dtm2<-as.data.frame(inspect(dtm2))#将词频矩阵转换为数据框格式得到
A document-term matrix (5 documents, 783 terms)
Non-/sparse entries: 890/3025
Sparsity : 77%
Maximal term length: 65
Weighting : term frequency (tf)
3.8 文本挖掘——聚类分析
> d <- dist(dtm2, method = "euclidean") > fit <- hclust(d, method="ward") > plot(fit)
3.9 分析结果
事实上文件123是有关于时间序列实习笔记,其相似度最高,图中也显示了他们可以聚为一类,证明分析的可靠性。