R语言中文分词包jiebaR
分析,了解国家大事;也可以对微博信息进行分析,通过社交舆情看看大家的关注点。通过文本挖掘找到文章中的隐藏信息,对文章的结构进行分析,判断是不是同一个作者写文章;同时可以对邮件分析,结合bayes算法判断哪些是垃圾邮件,哪些是有用的邮件。
本文挖掘的第一步,就是要进行分词,分词将直接影响
文本挖掘的效果。
R语言在分词方面有很好的支持,接下来就给大家介绍一个不错的
R语言中文分词包“结巴分词”(jiebaR)。
目录
jiebaR包介绍
5分钟上手
分词引擎
配置词典
停止词过滤
关键词提取
1. jiebaR包介绍
结巴分词(jiebaR),是一款高效的
R语言中文分词包,底层使用的是C++,通过Rcpp进行调用很高效。结巴分词基于MIT协议,就是免费和开源的,感谢国人作者的给力支持,让R的可以方便的处理中文文本。
官方Github的地址:https://github.com/qinwf/jiebaR
本文所使用的系统环境
Win10 64bit
R: 3.2.3 x86_64-w64-mingw32/x64 b4bit
jiebaR包是在CRAN发布的标准库,安装起来非常简单,2条命令就可以了。
~ R
> install.packages("jiebaR")
> library("jiebaR")
如果想要安装开发版本,可以使用devtools来进行安装,devtools的介绍请参考文章:在巨人的肩膀前行 催化R包开发(http://blog.fens.me/r-package-faster/)
> library(devtools)
> install_github("qinwf/jiebaRD")
> install_github("qinwf/jiebaR")
> library("jiebaR")
开发版本安装,官方建议使用
Linux系统 gcc >= 4.6 编译,Windows需要安装 Rtools。
2. 5分钟上手
5分钟上手,直接看第一个例子吧,对一段文字进行分词。
> wk = worker()
> wk["我是《R的极客理想》图书作者"]
[1] "我是" "R" "的" "极客" "理想" "图书" "作者"
> wk["我是
R语言的深度用户"]
[1] "我" "是" "R" "语言" "的" "深度" "用户"
很简单地,2行代码,就完成了中文分词。
jiebaR提供了3种分词语句的写法,例子上面的用[]符号的语法,还可以使用<=符合语法,或者使用segment()函数。虽然形式不同,但是分词效果是一样的。 使用<=符号的语法,如下
> wk<='另一种符合的语法'
[1] "另" "一种" "符合" "的" "语法"
使用segment()函数的语法,如下
> segment( "segment()函数语句的写法" , wk )
[1] "segment" "函数" "语句" "的" "写法"
如果你觉得很神奇,想了解如何自定义操作符的,可以检查项目的源代码quick.R文件https://github.com/qinwf/jiebaR/blob/master/R/quick.R
# <= 符号定义
`<=.qseg`<-function(qseg, code){
if(!exists("quick_worker",envir = .GlobalEnv ,inherits = F) ||
.GlobalEnv$quick_worker$PrivateVarible$timestamp != TIMESTAMP){
if(exists("qseg",envir = .GlobalEnv,inherits = FALSE ) )
rm("qseg",envir = .GlobalEnv)
modelpath = file.path(find.package("jiebaR"),"model","model.rda")
quickparam = readRDS(modelpath)
if(quickparam$dict == "AUTO") quickparam$dict = DICTPATH
if(quickparam$hmm == "AUTO") quickparam$hmm = HMMPATH
if(quickparam$user == "AUTO") quickparam$user = USERPATH
if(quickparam$stop_word == "AUTO") quickparam$stop_word = STOPPATH
if(quickparam$idf == "AUTO") quickparam$idf = IDFPATH
createquickworker(quickparam)
setactive()
}
//..代码省略
}
# [ 符号定义
`[.qseg`<- `<=.qseg`
我们也可以直接对文本文件进行分词,在当前目录新建一个文本文件idea.txt。
~ notepad idea.txt
R的极客理想系列文章,涵盖了R的思想,使用,工具,创新等的一系列要点,以我个人的学习和体验去诠释R的强大。
R语言作为统计学一门语言,一直在小众领域闪耀着光芒。直到大数据的爆发,
R语言变成了一门炙手可热的数据分析的利器。随着越来越多的工程背景的人的加入,
R语言的社区在迅速扩大成长。现在已不仅仅是统计领域,教育,银行,电商,互联网….都在使用
R语言。
当然,我们运行分词程序,会在当前目录生成一个新的分词结果的文件。
> wk['./idea.txt']
[1] "./idea.segment.2016-07-20_23_25_34.txt"
打开文件idea.segment.2016-07-20_23_25_34.txt,整个本文以空格进行分词。
~ notepad idea.segment.2016-07-20_23_25_34.txt
R 的 极客 理想 系列 文章 涵盖 了 R 的 思想 使用 工具 创新 等 的 一系列 要点 以 我 个人 的 学习 和 体验 去 诠释 R 的 强大 R 语言 作为 统计学 一门 语言 一直 在 小众 领域 闪耀着 光芒 直到 大 数据 的 爆发 R 语言 变成 了 一门 炙手可热 的 数据分析 的 利器 随着 越来越 多 的 工程 背景 的 人 的 加入 R 语言 的 社区 在 迅速 扩大 成长 现在 已 不仅仅 是 统计 领域 教育 银行 电商 互联网 都 在 使用 R 语言
是不是很简单,5分钟实践就能完成分词的任务。
3. 分词引擎
在调用worker()函数时,我们实际是在加载jiebaR库的分词引擎。jiebaR库提供了7种分词引擎。
混合模型(MixSegment):是四个分词引擎里面分词效果较好的类,结它合使用最大概率法和隐式马尔科夫模型。
最大概率法(MPSegment) :负责根据Trie树构建有向无环图和进行动态规划算法,是分词算法的核心。
隐式马尔科夫模型(HMMSegment):是根据基于人民日报等语料库构建的HMM模型来进行分词,主要算法思路是根据(B,E,M,S)四个状态来代表每个字的隐藏状态。 HMM模型由dict/hmm_model.utf8提供。分词算法即viterbi算法。
索引模型(QuerySegment):先使用混合模型进行切词,再对于切出来的较长的词,枚举句子中所有可能成词的情况,找出词库里存在。
标记模型(tag)
Simhash模型(simhash)
关键词模型(keywods)
如果你不太关心引擎的事,那么直接用官方推荐的混合模型(默认选择)就行了。查看worker()函数的定义。
worker(type = "mix", dict = DICTPATH, hmm = HMMPATH, user = USERPATH,
idf = IDFPATH, stop_word = STOPPATH, write = T, qmax = 20, topn = 5,
encoding = "UTF-8", detect = T, symbol = F, lines = 1e+05,
output = NULL, bylines = F, user_weight = "max")
参数列表:
type, 引擎类型
dict, 系统词典
hmm, HMM模型路径
user, 用户词典
idf, IDF词典
stop_word, 关键词用停止词库
write, 是否将文件分词结果写入文件,默认FALSE
qmax, 最大成词的字符数,默认20个字符
topn, 关键词数,默认5个
encoding, 输入文件的编码,默认UTF-8
detect, 是否编码检查,默认TRUE
symbol, 是否保留符号,默认FALSE
lines, 每次读取文件的最大行数,用于控制读取文件的长度。大文件则会分次读取。
output, 输出路径
bylines, 按行输出
user_weight, 用户权重
我们在调用worker()时,就加载了分词引擎,可以打印出来,查看分词的引擎的配置。
> wk = worker()
> wk
Worker Type: Jieba Segment
Default Method : mix # 混合模型
Detect Encoding : TRUE # 检查编码
Default Encoding: UTF-8 # UTF-8
Keep Symbols : FALSE # 不保留符号
Output Path : # 输出文件目录
Write File : TRUE # 写文件
By Lines : FALSE # 不行输出
Max Word Length : 20 # 最大单单词长度
Max Read Lines : 1e+05 # 最大读入文件行数
Fixed Model Components:
$dict # 系统词典
[1] "D:/tool/R-3.2.3/library/jiebaRD/dict/jieba.dict.utf8"
$user # 用户词典
[1] "D:/tool/R-3.2.3/library/jiebaRD/dict/user.dict.utf8"
$hmm # 隐式马尔科夫模型模型
[1] "D:/tool/R-3.2.3/library/jiebaRD/dict/hmm_model.utf8"
$stop_word # 停止词,无
NULL
$user_weight # 用户词典权重
[1] "max"
$timestamp # 时间戳
[1] 1469027302
$default $detect $encoding $symbol $output $write $lines $bylines can be reset.
如果我们想改变分词引擎的配置项,可以在调用worker()创建分词引擎时,也可以通过wk$XX来进行设置。如果想了解wk是什么类型的对象,我们通过pryr包的otype的函数来检查wk对象的类型。关于pryr包的详细使用,请参考文章撬动R内核的高级工具包pryr:http://blog.fens.me/r-pryr/
# 加载 pryr包
> library(pryr)
> otype(wk) # 面向对象的类型检查
[1] "S3"
> class(wk) # 查看class是属性
[1] "jiebar" "segment" "jieba"
4. 配置词典
对于分词的结果好坏的关键因素是词典,jiebaR默认有配置标准的词典。对于我们的使用来说,不同行业或不同的文字类型,最好用专门的分词词典。在jiebaR中通过show_dictpath()函数可以查看默认的标准词典,可以通过上一小节介绍的配置项,来指定我们自己的词典。日常对话的常用词典,比如搜狗输入法的词库。
# 查看默认的词库位置
> show_dictpath()
[1] "D:/tool/R-3.2.3/library/jiebaRD/dict"
# 查看目录
> dir(show_dictpath())
[1] "D:/tool/R-3.2.3/library/jiebaRD/dict"
[1] "backup.rda" "hmm_model.utf8" "hmm_model.zip"
[4] "idf.utf8" "idf.zip" "jieba.dict.utf8"
[7] "jieba.dict.zip" "model.rda" "README.md"
[10] "stop_words.utf8" "user.dict.utf8"
看到词典目录中,包括了多个文件。
jieba.dict.utf8, 系统词典文件,最大概率法,utf8编码的
hmm_model.utf8, 系统词典文件,隐式马尔科夫模型,utf8编码的
user.dict.utf8, 用户词典文件,utf8编码的
stop_words.utf8,停止词文件,utf8编码的
idf.utf8,IDF语料库,utf8编码的
jieba.dict.zip,jieba.dict.utf8的压缩包
hmm_model.zip,hmm_model.utf8的压缩包
idf.zip,idf.utf8的压缩包
backup.rda,无注释
model.rda,无注释
README.md,说明文件
打开系统词典文件jieba.dict.utf8,并打印前50行。
> scan(file="D:/tool/R-3.2.3/library/jiebaRD/dict/jieba.dict.utf8",
+ what=character(),nlines=50,sep='\n',
+ encoding='utf-8',fileEncoding='utf-8')
Read 50 items
[1] "1号店 3 n" "1號店 3 n" "4S店 3 n" "4s店 3 n"
[5] "AA制 3 n" "AB型 3 n" "AT&T 3 nz" "A型 3 n"
[9] "A座 3 n" "A股 3 n" "A輪 3 n" "A轮 3 n"
[13] "BB机 3 n" "BB機 3 n" "BP机 3 n" "BP機 3 n"
[17] "B型 3 n" "B座 3 n" "B股 3 n" "B超 3 n"
[21] "B輪 3 n" "B轮 3 n" "C# 3 nz" "C++ 3 nz"
[25] "CALL机 3 n" "CALL機 3 n" "CD机 3 n" "CD機 3 n"
[29] "CD盒 3 n" "C座 3 n" "C盘 3 n" "C盤 3 n"
[33] "C語言 3 n" "C语言 3 n" "D座 3 n" "D版 3 n"
[37] "D盘 3 n" "D盤 3 n" "E化 3 n" "E座 3 n"
[41] "E盘 3 n" "E盤 3 n" "E通 3 n" "F座 3 n"
[45] "F盘 3 n" "F盤 3 n" "G盘 3 n" "G盤 3 n"
[49] "H盘 3 n" "H盤 3 n"
我们发现系统词典每一行都有三列,并以空格分割,第一列为词项,第二列为词频,第三列为词性标记。
打开用户词典文件user.dict.utf8,并打印前50行。
> scan(file="D:/tool/R-3.2.3/library/jiebaRD/dict/user.dict.utf8",
+ what=character(),nlines=50,sep='\n',
+ encoding='utf-8',fileEncoding='utf-8')
Read 5 items
[1] "
云计算" "韩玉鉴赏" "蓝翔 nz" "CEO" "江大桥"
用户词典第一行有二列,,第一列为词项,第二列为词性标记,没有词频的列。用户词典默认词频为系统词库中的最大词频。
jiebaR包关于词典词性标记,采用ictclas的标记方法。ICTCLAS 汉语词性标注集。
代码名称帮助记忆的诠释
Ag形语素形容词性语素。形容词代码为a,语素代码g前面置以A。
a形容词取英语形容词adjective的第1个字母。
ad副形词直接作状语的形容词。形容词代码a和副词代码d并在一起。
an名形词具有名词功能的形容词。形容词代码a和名词代码n并在一起。
b区别词取汉字"别"的声母。
c连词取英语连词conjunction的第1个字母。
Dg副语素副词性语素。副词代码为d,语素代码g前面置以D。
d副词取adverb的第2个字母,因其第1个字母已用于形容词。
e叹词取英语叹词exclamation的第1个字母。
f方位词取汉字"方"的声母。
g语素绝大多数语素都能作为合成词的"词根",取汉字"根"的声母。
h前接成分取英语head的第1个字母。
i成语取英语成语idiom的第1个字母。
j简称略语取汉字"简"的声母。
k后接成分
l习用语习用语尚未成为成语,有点"临时性",取"临"的声母。
m数词取英语numeral的第3个字母,n,u已有他用。
Ng名语素名词性语素。名词代码为n,语素代码g前面置以N。
n名词取英语名词noun的第1个字母。
nr人名名词代码n和"人(ren)"的声母并在一起。
ns地名名词代码n和处所词代码s并在一起。
nt机构团体"团"的声母为t,名词代码n和t并在一起。
nz其他专名"专"的声母的第1个字母为z,名词代码n和z并在一起。
o拟声词取英语拟声词onomatopoeia的第1个字母。
p介词取英语介词prepositional的第1个字母。
q量词取英语quantity的第1个字母。
r代词取英语代词pronoun的第2个字母,因p已用于介词。
s处所词取英语space的第1个字母。
Tg时语素时间词性语素。时间词代码为t,在语素的代码g前面置以T。
t时间词取英语time的第1个字母。
u助词取英语助词auxiliary 的第2个字母,因a已用于形容词。
Vg动语素动词性语素。动词代码为v。在语素的代码g前面置以V。
v动词取英语动词verb的第一个字母。
vd副动词直接作状语的动词。动词和副词的代码并在一起。
vn名动词指具有名词功能的动词。动词和名词的代码并在一起。
w标点符号
x非语素字非语素字只是一个符号,字母x通常用于代表未知数、符号。
y语气词取汉字"语"的声母。
z状态词取汉字"状"的声母的前一个字母。
下面我们自定义一个用户词典,来试试效果。编写词典文件,user.utf8。
~ notepad user.utf8
R语言
R的极客理想
大数据
数据
使用我们的自定义的用户词典,对刚才的文本再进行分词。
> wk = worker(user='user.utf8')
> wk['./idea.txt']
[1] "./idea.segment.2016-07-21_11_14_24.txt"
对比2次产生的分词结果,idea.segment.2016-07-20_23_25_34.txt 和 idea.segment.2016-07-21_11_14_24.txt。
在实际使用中,jiebaR默认提供的用户词典只有5个单词,太简单了,肯定是不够用的。我们可以用搜狗词典,来丰富用户自己的词库。接下来,让我们配置搜狗词典。你需要安装一个搜狗输入法,具体的安装过程不再解释。
我安装的是搜狗五笔输入法,找到搜狗的安装目录,并找到词典文件。我的搜狗词典,在下面的安装位置。
C:\Program Files (x86)\SogouWBInput\2.1.0.1288\scd\17960.scel
把17960.scel文件复制到自己的项目目录里,用文本编辑器打开文件,发现是二进制的。那么我需要用工具进行转换,把二进制的词典转成我们可以使用的文本文件。jiebaR包的作者,同时开发了一个cidian项目,可以转换搜狗的词典,那么我们只需要安装cidian包即可。
安装cidian项目
> install.packages("devtools")
> install.packages("stringi")
> install.packages("pbapply")
> install.packages("Rcpp")
> install.packages("RcppProgress")
> library(devtools)
> install_github("qinwf/cidian")
> library(cidian)
转换二进制词典到文本文件。
# 转换
> decode_scel(scel = "./17960.scel",cpp = TRUE)
output file: ./17960.scel_2016-07-21_00_22_11.dict
# 查看生成的词典文件
> scan(file="./17960.scel_2016-07-21_00_22_11.dict",
+ what=character(),nlines=50,sep='\n',
+ encoding='utf-8',fileEncoding='utf-8')
Read 50 items
[1] "阿坝州 n" "阿百川 n" "阿班 n"
[4] "阿宾 n" "阿波菲斯 n" "阿不都热希提 n"
[7] "阿不都西库尔 n" "阿不力克木 n" "阿尔姆格伦 n"
[10] "阿尔沙文 n" "阿肥星 n" "阿菲正传 n"
[13] "阿密特 n" "阿穆 n" "阿穆隆 n"
[16] "阿帕鲁萨镇 n" "阿披实 n" "阿衰 n"
[19] "阿霞 n" "艾奥瓦 n" "爱不疚 n"
[22] "爱的错位 n" "爱得得体 n" "爱的火焰 n"
[25] "爱的流刑地 n" "爱得起 n" "埃夫隆 n"
[28] "爱搞网 n" "爱国红心 n" "爱呼 n"
[31] "爱就宅一起 n" "埃克希儿 n" "爱没有错 n"
[34] "埃蒙斯 n" "爱奴新传 n" "爱起点 n"
[37] "爱情的牙齿 n" "爱情海滨 n" "爱情节 n"
[40] "爱情美的样子 n" "爱情无限谱 n" "爱情占线 n"
[43] "爱情转移 n" "爱情左灯右行 n" "爱上你是一个错 n"
[46] "矮哨兵 n" "爱是妥协 n" "爱似水仙 n"
[49] "爱太痛 n" "爱无界 n"
接下来,直接把搜狗词典配置到我们的分词库中,就可以直接使用了。把搜狗词典文件改名,从17960.scel_2016-07-21_00_22_11.dict到user.dict.utf8,然后替换D:\tool\R-3.2.3\library\jiebaRD\dict目录下面的user.dict.utf8。这样默认的用户词典,就是搜狗词典了。很酷吧!
5. 停止词过滤
停止词就是分词过程中,我们不需要作为结果的词,像英文的语句中有很多的a,the,or,and等,中文语言中也有很多,比如 的,地,得,我,你,他。这些词因为使用频率过高,会大量出现在一段文本中,对于分词后的结果,在统计词频的时候会增加很多的噪音,所以我们通常都会将这些词进行过滤。
在jiebaR中,过滤停止词有2种方法,一种是通过配置stop_word文件,另一种是使用filter_segment()函数。
首先我们先来看,通过配置stop_word文件的方法。新建一个stop_word.txt文件。
~ notepad stop_word.txt
我
我是
加载分词引擎,并配置停止词过滤。
> wk = worker(stop_word='stop_word.txt')
> segment<-wk["我是《R的极客理想》图书作者"]
> segment
[1] "R" "的" "极客" "理想" "图书" "作者"
上面的文本,我们把"我是"通过停止词进行了过滤。如果还想过滤“作者”一词,可以动态的调用filter_segment()函数。
> filter<-c("作者")
> filter_segment(segment,filter)
[1] "R" "的" "极客" "理想" "图书"
6. 关键词提取
关键词提取是文本处理非常重要的一个环节,一个经典算法是TF-IDF算法。其中,TF(Term Frequency)代表词频,IDF(Inverse Document Frequency)表示逆文档频率。如果某个词在文章中多次出现,而且不是停止词,那么它很可能就反应了这段文章的特性,这就是我们要找的关键词。再通过IDF来算出每个词的权重,不常见的词出现的频率越高,则权重越大。计算TF-IDF的公式为:
TF-IDF = TF(词频) * 逆文档频率(IDF)
对文档中每个词计算TF-IDF的值,把结果从大到小排序,就得到了这篇文档的关键性排序列表。
jiebaR包的关键词提取提取的实现,也是使用了TF-IDF的算法。在安装目录中的idf.utf8文件,为IDF的语料库。查看idf.utf8内容。
> scan(file="D:/tool/R-3.2.3/library/jiebaRD/dict/idf.utf8",
+ what=character(),nlines=50,sep='\n',
+ encoding='utf-8',fileEncoding='utf-8')
Read 50 items
[1] "劳动防护 13.900677652" "生化学 13.900677652"
[3] "奥萨贝尔 13.900677652" "考察队员 13.900677652"
[5] "岗上 11.5027823792" "倒车档 12.2912397395"
[7] "编译 9.21854642485" "蝶泳 11.1926274509"
[9] "外委 11.8212361103" "故作高深 11.9547675029"
[11] "尉遂成 13.2075304714" "心源性 11.1926274509"
[13] "现役军人 10.642581114" "杜勃留 13.2075304714"
[15] "包天笑 13.900677652" "贾政陪 13.2075304714"
[17] "托尔湾 13.900677652" "多瓦 12.5143832909"
[19] "多瓣 13.900677652" "巴斯特尔 11.598092559"
[21] "刘皇帝 12.8020653633" "亚历山德罗夫 13.2075304714"
[23] "社会公众 8.90346537821" "五百份 12.8020653633"
[25] "两点阈 12.5143832909" "多瓶 13.900677652"
[27] "冰天 12.2912397395" "库布齐 11.598092559"
[29] "龙川县 12.8020653633" "银燕 11.9547675029"
[31] "历史风貌 11.8212361103" "信仰主义 13.2075304714"
[33] "好色 10.0088573539" "款款而行 12.5143832909"
[35] "凳子 8.36728816325" "二部 9.93038573842"
[37] "卢巴 12.1089181827" "五百五 13.2075304714"
[39] "畅叙 11.598092559" "吴栅子 13.2075304714"
[41] "智力竞赛 13.900677652" "库邦 13.2075304714"
[43] "非正义 11.3357282945" "编订 10.2897597393"
[45] "悲号 12.8020653633" "陈庄搭 13.2075304714"
[47] "二郎 9.62401153296" "电光石火 11.8212361103"
[49] "抢球 11.9547675029" "南澳大利亚 10.9562386728"
idf.utf8文件每一行有2列,第一列是词项,第二列为权重。然后,我通过计算文档的词频(TF),与语料库的IDF值相乘,就可以得到TF-IDF值,从而提取文档的关键词。
比如,我们对下面的文本内容进行关键词的提取。
> wk = worker()
> segment<-wk["R的极客理想系列文章,涵盖了R的思想,使用,工具,创新等的一系列要点,以我个人的学习和体验去诠释R的强大。"]
# 计算词频
> freq(segment)
char freq
1 创新 1
2 了 1
3 文章 1
4 强大 1
5 R 3
6 个人 1
7 的 5
8 诠释 1
9 和 1
10 一系列 1
11 使用 1
12 以 1
13 等 1
14 极客 1
15 理想 1
16 思想 1
17 涵盖 1
18 系列 1
19 去 1
20 我 1
21 工具 1
22 学习 1
23 体验 1
24 要点 1
# 取TF-IDF的前5的关键词
> keys = worker("keywords",topn=5)
# 计算关键词
> vector_keywords(segment,keys)
11.7392 8.97342 8.23425 8.2137 7.43298
"极客" "诠释" "要点" "涵盖" "体验"
使用jieba
R包处理分词确实简单,几行的代码就能实现分词的各种算法操作。有了这个工具,我们就可以文档中,发现各种语言规则进行
文本挖掘了。
CDA数据分析师考试相关入口一览(建议收藏):
▷ 想报名CDA认证考试,点击>>>
“CDA报名”
了解CDA考试详情;
▷ 想加入CDA考试题库,点击>>> “CDA题库” 了解CDA考试详情;
▷ 想学习CDA考试教材,点击>>> “CDA教材” 了解CDA考试详情;
▷ 想查询CDA考试成绩,点击>>> “CDA成绩” 了解CDA考试详情;
▷ 想了解CDA考试含金量,点击>>> “CDA含金量” 了解CDA考试详情;
▷ 想获取CDA考试时间/费用/条件/大纲/通过率,点击 >>>“CDA考试官网” 了解CDA考试详情;