1. 首页
  2. 数据挖掘

R包之tm:文本挖掘包

R包之tm:文本挖掘包

  • 简介

  • 安装

  • 数据输入—文集(corpus)

  • 数据输出

  • 查看语料库(corpora)

    • 查看某几条信息

    • 查看单个文档元数据

    • 查看单个文档内容

    • 查看多个文档内容

  • 变换(transformation)

  • 过滤器

  • 元数据管理

  • 标准操作和函数

  • 创建文档-单词矩阵

  • 文档-单词矩阵的操作

  • 字典

  • 关于中文支持

本文参考文档:

  1. tm的使用指南 :http://mirror.bjtu.edu.cn/cran/web/packages/tm/vignettes/tm.pdf

  2. tm手册 :http://mirror.bjtu.edu.cn/cran/web/packages/tm/tm.pdf

简介

tm 即text mining,是用来做文本挖掘的一个R包,是一个进行自然语言处理的基础包。它提供了一些做文本挖掘的基础设施,比如数据输入,文集处理,预处理,元数据管理,创建单词-文本矩阵。

安装

该包的安装方法是install.packages("tm")

数据输入—文集(corpus)

文集代表一个文档集,通常一个文件就是一个文档。多个文档构成一个文集。文集是一个抽象的概念,具体的实现方式有几种,一个是VCorpus(Volatile Corpus),这种文集完全存储在内存中。故而不能很大。这个文集的创建方法为VCorpus(x,readerControl)。 另一个实现是PCorpus1(Permanent Corpus),这种实现方式下,内存中只是存储文档的指针,真正的文档存储在磁盘上(文件或者数据库)。

文集创建的第一个参数x必须是一个Source对象,tm提供了一些预定义的source。比如DirSrouce,VectorSource,DataframeSource等,它们分别用来处理一个目录,一个向量(每个元素为一个文档),和数据框结构(比如csv)的文档。可以利用getSources()来得到所有可用的source,用户也可以建立自己的source。

文集创建的第二个参数是readerControl,这个参数必需是一个列表,其中包含组件readerlanguage。其中:

  • reader负责创建一个文档。而文档的来源是source传递过来的每个元素。下面是简单的处理流程

    source --> elements ---> reader ---> document

    其中,tm包中有几种reader,比如readPlain(),readPDF(),readDOC()等等,可以利用getReaders()来获得所有可以的reader

    每个source都对应有一个缺省的reader,比如DirSource的reader就是读入文件,把文件的内容作为字符串。这个reader是可以被替换的。

  • language指明文本的语言

因此,对于包tm目录下的texts/txt目录下的文本文件可以这样做成一个文集

library(tm)#> Loading required package: NLPtxt <- system.file("texts","txt",package="tm") vid = VCorpus(DirSource(txt, encoding = "UTF-8"), readerControl = list(language="lat")) vid#> <<VCorpus>>#> Metadata: corpus specific: 0, document level (indexed): 0#> Content: documents: 5

最简单的VectorSource,可以用来最简单的测试,比如

docs <- c("hello doc1", "hello doc2")  VCorpus(VectorSource(docs))#> <<VCorpus>>#> Metadata: corpus specific: 0, document level (indexed): 0#> Content: documents: 2

最后可以看一个指定外部reader的例子

reut21578 <- system.file("texts", "crude", package = "tm") reuters <- VCorpus(DirSource(reut21578),          readerControl = list(reader = readReut21578XMLasPlain))

数据输出

文集中的数据可以直接输出,比如前面读入的文集,可以这样写到磁盘上去writeCorpus(vid), 每个文档会生成一个文件

查看语料库(corpora)

print(vid)只是给出了最简单的信息,要查看更多的信息,可使用inspect()

查看某几条信息

inspect(vid[1:2])#> <<VCorpus>>#> Metadata: corpus specific: 0, document level (indexed): 0#> Content: documents: 2#> #> [[1]]#> <<PlainTextDocument>>#> Metadata: 7#> Content: chars: 676#> #> [[2]]#> <<PlainTextDocument>>#> Metadata: 7#> Content: chars: 700

查看单个文档元数据

meta(vid[[2]])#>  author    : character(0)#>  datetimestamp: 2016-03-09 01:45:14#>  description : character(0)#>  heading   : character(0)#>  id      : ovid_2.txt#>  language   : lat#>  origin    : character(0)

查看单个文档内容

as.character(vid[[2]])#> [1] "  quas Hector sensurus erat, poscente magistro"  #> [2] "     verberibus iussas praebuit ille manus."  #> [3] "  Aeacidae Chiron, ego sum praeceptor Amoris:"  #> [4] "     saevus uterque puer, natus uterque dea."  #> [5] "  sed tamen et tauri cervix oneratur aratro,"   #> [6] ""                          #> [7] "     frenaque magnanimi dente teruntur equi;"  #> [8] "  et mihi cedet Amor, quamvis mea vulneret arcu" #> [9] "     pectora, iactatas excutiatque faces."   #> [10] "  quo me fixit Amor, quo me violentius ussit,"  #> [11] "     hoc melior facti vulneris ultor ero:"   #> [12] ""                          #> [13] "  non ego, Phoebe, datas a te mihi mentiar artes,"#> [14] "     nec nos aëriae voce monemur avis,"     #> [15] "  nec mihi sunt visae Clio Cliusque sorores"   #> [16] "     servanti pecudes vallibus, Ascra, tuis:"  #> [17] "  usus opus movet hoc: vati parete perito;"

查看多个文档内容

lapply(vid[1:2],as.character)#> $ovid_1.txt#> [1] "  Si quis in hoc artem populo non novit amandi,"  #> [2] "     hoc legat et lecto carmine doctus amet."   #> [3] "  arte citae veloque rates remoque moventur,"    #> [4] "     arte leves currus: arte regendus amor."   #> [5] ""                           #> [6] "  curribus Automedon lentisque erat aptus habenis," #> [7] "     Tiphys in Haemonia puppe magister erat:"   #> [8] "  me Venus artificem tenero praefecit Amori;"    #> [9] "     Tiphys et Automedon dicar Amoris ego."    #> [10] "  ille quidem ferus est et qui mihi saepe repugnet:"#> [11] ""                           #> [12] "     sed puer est, aetas mollis et apta regi."  #> [13] "  Phillyrides puerum cithara perfecit Achillem,"  #> [14] "     atque animos placida contudit arte feros."  #> [15] "  qui totiens socios, totiens exterruit hostes,"  #> [16] "     creditur annosum pertimuisse senem."     #> #> $ovid_2.txt#> [1] "  quas Hector sensurus erat, poscente magistro"  #> [2] "     verberibus iussas praebuit ille manus."  #> [3] "  Aeacidae Chiron, ego sum praeceptor Amoris:"  #> [4] "     saevus uterque puer, natus uterque dea."  #> [5] "  sed tamen et tauri cervix oneratur aratro,"   #> [6] ""                          #> [7] "     frenaque magnanimi dente teruntur equi;"  #> [8] "  et mihi cedet Amor, quamvis mea vulneret arcu" #> [9] "     pectora, iactatas excutiatque faces."   #> [10] "  quo me fixit Amor, quo me violentius ussit,"  #> [11] "     hoc melior facti vulneris ultor ero:"   #> [12] ""                          #> [13] "  non ego, Phoebe, datas a te mihi mentiar artes,"#> [14] "     nec nos aëriae voce monemur avis,"     #> [15] "  nec mihi sunt visae Clio Cliusque sorores"   #> [16] "     servanti pecudes vallibus, Ascra, tuis:"  #> [17] "  usus opus movet hoc: vati parete perito;"

变换(transformation)

变换指通过tm_map函数来对文集中所有的文档作用一个函数的过程。比如停用词剔除等。每个变换只是作用在一个文档 上,tm_map来把它作用到所有的文档。

比如

  • 剔除多余的空白tm_map(vid,stripWhitespace)

  • 转换为小写tm_map(vid,content_transformer(tolower))

    其中的content_transformer是一个修改文档内容的方便的函数,tolower可以是任何其他的字符串修改函数

  • 移除停用词

    reuters <- tm_map(reuters, removeWords, stopwords("english"))

过滤器

过滤器可以移除不感兴趣的(或者感兴趣的)文档。tm提供了tm_filter函数,这个函数的原型为

  1. tm_filter(x, FUN,...)

  2. tm_index(x,FUN,...)

其中的FUN函数出入为一片文档,输出为一个bool值。表示是否接受该文档。第二个版本tm_index只是返回满足条件的index,前者返回一个文集,下面是一个使用示例:

data("crude")# Full-text searchtm_filter(crude, FUN = function(x) any(grep("co[m]?pany", content(x))))

元数据管理

元数据分为两个层次,一个是文集级别的元数据,一个是文档级别的元数据。要获得元数据,最简单的是 使用meta()函数。每篇文档,有些预定义的元数据(比如author),但是每篇文档也可以添加自定义的 元数据标签。如下所示,分别用DublinCoremeta函数来修改一个文档的元数据

data(crude)DublinCore(crude[[1]], "Creator") <- "Ano Nymous"meta(crude[[1]])#>  author    : Ano Nymous#>  datetimestamp: 1987-02-26 17:00:56#>  description : #>  heading   : DIAMOND SHAMROCK (DIA) CUTS CRUDE PRICES#>  id      : 127#>  language   : en#>  origin    : Reuters-21578 XML#>  topics    : YES#>  lewissplit  : TRAIN#>  cgisplit   : TRAINING-SET#>  oldid    : 5670#>  places    : usa#>  people    : character(0)#>  orgs     : character(0)#>  exchanges  : character(0)meta(crude[[1]], "author") <- "Jiang Hang"meta(crude[[1]])#>  author    : Jiang Hang#>  datetimestamp: 1987-02-26 17:00:56#>  description : #>  heading   : DIAMOND SHAMROCK (DIA) CUTS CRUDE PRICES#>  id      : 127#>  language   : en#>  origin    : Reuters-21578 XML#>  topics    : YES#>  lewissplit  : TRAIN#>  cgisplit   : TRAINING-SET#>  oldid    : 5670#>  places    : usa#>  people    : character(0)#>  orgs     : character(0)#>  exchanges  : character(0)

下面是修改文集级别元数据的列子

meta(crude, tag = "url", type = "corpus") <- "http://www.bagualu.net"meta(crude, type = "corpus")#> $url#> [1] "http://www.bagualu.net"#> #> attr(,"class")#> [1] "CorpusMeta"

每个元数据的数据可以是dataframe结构的。

标准操作和函数

标准的操作符[,[[,[<-,[[<-,c(),lapply()可以直接作用在corpora(语料库)上

创建文档-单词矩阵

tm中,函数TermDocumentMatrixDocumentTermMatrix可直接创建文档-单词矩阵,这二者的却别 在于矩阵的行是文档还是单词

dtm <- DocumentTermMatrix(reuters)inspect(dtm[5:10, 740:743])#> <<DocumentTermMatrix (documents: 6, terms: 4)>>#> Non-/sparse entries: 2/22#> Sparsity      : 92%#> Maximal term length: 9#> Weighting     : term frequency (tf)#> #>   Terms#> Docs needs. negative negotiate neither#>  211   0    0     0    0#>  236   0    0     0    0#>  237   1    0     0    0#>  242   0    0     0    0#>  246   0    0     0    0#>  248   0    1     0    0

文档-单词矩阵的操作

有了矩阵以后,可以有很多R函数可以作用于它,但是tm包提供了一些常用的函数,比如你想找到那些至少 出现了10次的单词,使用findFreqTerms()函数

findFreqTerms(dtm,10)#> [1] "about"   "and"    "are"    "bpd"    "but"    #> [6] "crude"   "dlrs"    "for"    "from"    "government"#> [11] "has"    "its"    "kuwait"   "last"    "market"  #> [16] "mln"    "new"    "not"    "official"  "oil"    #> [21] "one"    "opec"    "pct"    "price"   "prices"  #> [26] "reuter"   "said"    "said."   "saudi"   "sheikh"  #> [31] "that"    "the"    "they"    "u.s."    "was"    #> [36] "were"    "will"    "with"    "would"

又比如,要找到与单词opec有0.8以上相关性的单词,使用findAssocs()

findAssocs(dtm,"opec",0.8)#> $opec#>  meeting emergency    oil   15.8 analysts  buyers   above #>   0.88   0.87   0.87   0.85   0.85   0.83   0.82 #>   said  ability #>   0.82   0.80

文档-单词矩阵通常很大。tm提供了移除稀疏元素的函数

inspect(removeSparseTerms(dtm,0.4))#> <<DocumentTermMatrix (documents: 20, terms: 8)>>#> Non-/sparse entries: 140/20#> Sparsity      : 12%#> Maximal term length: 6#> Weighting     : term frequency (tf)#> #>   Terms#> Docs and for its oil reuter said the was#>  127  1  2  3  5   1  1  5  1#>  144  9  5  6 11   1  9 17  1#>  191  0  2  1  2   1  1  4  0#>  194  1  2  1  1   1  1  4  1#>  211  2  2  1  1   1  3  8  0#>  236  7  4  8  7   1  6 15  7#>  237 11  3  3  3   1  0 30  2#>  242  3  1  0  3   1  3  6  1#>  246  9  6  3  4   1  4 18  2#>  248  6  2  2  9   1  5 27  4#>  273  5  4  0  5   1  5 21  1#>  349  2  0  0  3   1  1  5  0#>  352  3  0  2  5   1  1  7  1#>  353  1  2  2  4   1  1  4  3#>  368  1  0  1  3   1  2 11  2#>  489  5  4  2  4   1  2  8  0#>  502  6  5  2  4   1  2 13  0#>  543  0  3  2  2   1  2  5  1#>  704  5  3  1  3   1  3 21  0#>  708  0  0  0  1   1  0  0  1

字典

字典是字符串的集合,通常用一个字符串向量表示,可以在DocumentTermMatrix函数中指定一个 字典,这样生成的矩阵中,就只有字典中出现的词语,不在字典中的词语不会出现在文档单词矩阵中 如下所示

inspect(DocumentTermMatrix(reuters,             list(dictionary = c("prices", "crude", "oil"))))#> <<DocumentTermMatrix (documents: 20, terms: 3)>>#> Non-/sparse entries: 41/19#> Sparsity      : 32%#> Maximal term length: 6#> Weighting     : term frequency (tf)#> #>   Terms#> Docs crude oil prices#>  127   2  5   3#>  144   0 11   3#>  191   2  2   0#>  194   3  1   0#>  211   0  1   0#>  236   1  7   2#>  237   0  3   0#>  242   0  3   1#>  246   0  4   0#>  248   0  9   7#>  273   5  5   4#>  349   2  3   0#>  352   0  5   4#>  353   2  4   1#>  368   0  3   0#>  489   0  4   2#>  502   0  4   2#>  543   2  2   2#>  704   0  3   2#>  708   1  1   0

关于中文支持

利用缺省的reader读入文档时,如果文档为中文,tm还是会以空格作为单词的分割符。这样基本对中文不适用。为了能够处理中文,需要 图换掉缺省的reader。新的reader应该读入文章,并进行分词,然后将分词的结果保存为一个新的文件,该文件中,各中文单词以空格隔开 。然后再利用tm的缺省reader进行处理就可以了。关于自定义reader的格式,详见这篇博客


rmmseg4j 以前在cran中的,后来被移除了,原因是不符合java的源码政策 ( Archived on 2014-08-30 as does not comply with policy on Java sources. )


  1. 对于PCorpus而言,第三个参数dbControl必须是一个列表,它具有组件dbNamedbType(这个dbType必须是filehash包支持的数据库类型)。这里不做详细讨论。↩

来源:http://www.bagualu.net/wordpress/archives/6112

原文始发于微信公众号(PPV课数据科学社区):R包之tm:文本挖掘包

原创文章,作者:ppvke,如若转载,请注明出处:http://www.ppvke.com/archives/10534

联系我们

4000-51-9191

在线咨询:点击这里给我发消息

工作时间:周一至周五,9:30-18:30,节假日休息