2013-02-13 113 views
6

tm库中是否存在预构建函数,或者与之配合良好的函数?如何使用tm软件包计算R中的可读性

我现在的语料库装入TM,类似如下:

s1 <- "This is a long, informative document with real words and sentence structure: introduction to teaching third-graders to read. Vocabulary is key, as is a good book. Excellent authors can be hard to find." 
s2 <- "This is a short jibberish lorem ipsum document. Selling anything to strangers and get money! Woody equal ask saw sir weeks aware decay. Entrance prospect removing we packages strictly is no smallest he. For hopes may chief get hours day rooms. Oh no turned behind polite piqued enough at. " 
stuff <- rbind(s1,s2) 
d <- Corpus(VectorSource(stuff[,1])) 

我使用koRpus试过,但似乎傻在不同的包比我已经使用了一个retokenize。我也遇到了问题,它的返回对象的矢量化方式可以让我将结果重新合并为tm。 (也就是说,由于错误,它通常会返回比我的收藏中的文档数量更多或更少的可读性分数。)

我明白我可以做一个天真的计算,将元音解析为音节,但想要更彻底的包照顾边缘情况已经(地址沉默e等)。

我的可读性分数是Flesch-Kincaid或Fry。

我原本试图d是我的100个文件的文集:

f <- function(x) tokenize(x, format="obj", lang='en') 
g <- function(x) flesch.kincaid(x) 
x <- foreach(i=1:length(d), .combine='c',.errorhandling='remove') %do% g(f(d[[i]])) 

不幸的是,X返回少于100个文件,所以我不能用正确的文件关联的成功。 (这部分是我对R中的'foreach'和'lapply'的误解,但是我发现文本对象的结构足够困难,我无法适当地标记,应用flesch.kincaid,并且在合理的应用顺序中成功地检查错误声明。)

更新其他

两件事情我已经试过,试图将koRpus功能应用到TM对象...

  1. 参数传递到tm_map对象,使用默认分词器: tm_map(d,flesch.kincaid,force.lang="en",tagger=tokenize)

  2. 定义一个标记生成器,通过在

    f <- function(x) tokenize(x, format="obj", lang='en') 
    tm_map(d,flesch.kincaid,force.lang="en",tagger=f) 
    

这些返回的两个:

Error: Specified file cannot be found: 

然后列出d [1]的全文。似乎找到了它?我应该怎么做才能正确传递函数?

更新2

这是我得到的错误,当我尝试koRpus功能直接与lapply映射:

> lapply(d,tokenize,lang="en") 
Error: Unable to locate 
Introduction to teaching third-graders to read. Vocabulary is key, as is a good book. Excellent authors can be hard to find. 

这看起来像一个奇怪的错误---我几乎不认为这意味着它无法找到文本,但是在转储找到的文本之前,它找不到一些空白的错误代码(如'tokenizer')。

UPDATE 3

另一个问题与使用koRpus重新标记是重新标记(相对于TM标记器)是极为缓慢的和输出其标记化进展到stdout。无论如何,我已经试过如下:

f <- function(x) capture.output(tokenize(x, format="obj", lang='en'),file=NULL) 
g <- function(x) flesch.kincaid(x) 
x <- foreach(i=1:length(d), .combine='c',.errorhandling='pass') %do% g(f(d[[i]])) 
y <- unlist(sapply(x,slot,"Flesch.Kincaid")["age",]) 

我在这里的意图是将y对象的上方回重新绑定到我的tm(d)语料库作为元数据,meta(d, "F-KScore") <- y

不幸的是,应用到我的实际数据集,我得到错误信息:

Error in FUN(X[[1L]], ...) : 
    cannot get a slot ("Flesch.Kincaid") from an object of type "character" 

我觉得我的实际语料库的一个元素必须是NA,或太长,别的东西望而却步---和由于嵌套功能化,我无法准确追踪它是哪一个。

所以,目前看起来好像没有预建的函数来读取与tm库很好地匹配的分数。除非有人看到一个容易出错的解决方案,否则我可以将其纳入我的函数调用中,以处理无法标记某些显然是错误的,格式错误的文档?

+0

不能使用与TM'tm_map'的'从koRpus flesh.kincaid'? – 2013-02-13 17:58:04

+0

我似乎无法。它说:“错误:没有指定语言!”对于tm_map的'每一个变化(DD,flesch.kincaid)'我能想到的,如'tm_map(DD,flesch.kincaid, “恩”)'等 – Mittenchops 2013-02-13 18:01:18

+0

所以,我咨询了另一个问题,SO(HTTP:/ /stackoverflow.com/questions/6827299/r-apply-function-with-multiple-parameters)关于如何将参数传递给嵌套函数。我尝试过'tm_map(d,flesch.kincaid,force.lang =“en”,tagger = tokenize)',但得到一个错误,它找不到“指定的文件”,然后输出文档1的内容。 – Mittenchops 2013-02-13 19:35:04

回答

4

由于koRpus函数无法处理corpus对象,您会收到错误。最好创建一个kRp.tagged对象,然后应用所有koRpus功能。在这里,我将展示如何使用tm包的ovid数据执行此操作。我使用list.files来获取我的源文件列表。你只需要给你的源文本文件提供正确的路径。

ll.files <- list.files(path = system.file("texts", "txt", 
            package = "tm"), 
       full.names=T) 

然后我构建使用tokenize这与koRpus包给予了默认恶搞kRp.tagged对象的列表(这是建议报告使用TreeTagger但你需要安装它)一旦

ll.tagged <- lapply(ll.files, tokenize, lang="en") ## tm_map is just a wrapper of `lapply` 

我有我可以应用可读性公式的“标记”对象列表。由于flesch.kincaidreadability的包装,我将申请直接后者:

ll.readability <- lapply(ll.tagged,readability)   ## readability 
ll.freqanalysis <- lapply(ll.tagged,kRp.freq.analysis) ## Conduct a frequency analysis 
ll.hyphen <- lapply(ll.tagged,hyphen)     ## word hyphenation 

等......这一切产生S4对象的列表。该desc插槽提供了一个易于访问该表:

lapply(lapply(ll.readability ,slot,'desc'),    ## I apply desc to get a list 
     '[',c('sentences','words','syllables'))[[1]] ## I subset to get some indexes 
[[1]] 
[[1]]$sentences 
[1] 10 

[[1]]$words 
[1] 90 

[[1]]$syllables 
all s1 s2 s3 s4 
196 25 32 25 8 

例如,您可以使用的插槽hyphen得到一个数据帧有两个colums,字(复姓字)和syll(音节数) 。在这里,使用lattice,我绑定所有data.frames,为每个文档绘制dotplot

library(lattice) 
ll.words.syl <- lapply(ll.hyphen,slot,'hyphen')  ## get the list of data.frame 
ll.words.syl <- lapply(seq_along(ll.words.syl),  ## add a column to distinguish docs 
     function(i)cbind(ll.words.syl[[i]],group=i)) 
dat.words.syl <- do.call(rbind,ll.words.syl) 
dotplot(word~syll|group,dat.words.syl, 
     scales=list(y=list(relation ='free'))) 

enter image description here

+0

这是一个美丽的答案和有用的,但如果我有的格式没有存储在本地作为ovid文本文件,我仍然不知道如何做标记化并将其关联到tm对象。我已经使用该库进行其他分析,所以我仍然需要将koRpus可读性分数锁定到这些实体的方法,即使我完全为此算法切换到koRpus。 – Mittenchops 2013-02-19 21:30:57

+0

@Mittenchops谢谢!确定没有本地,但他们在哪里?你是指通过获取社区来获得tm ..如果评分是通过文档,很容易将它作为一个** meta **放置在你的tm对象中,比如'meta(doc [i],'scoree')< - 分数... ... – agstudy 2013-02-19 21:37:20

+0

谢谢,@agstudy。我在上面添加了一个更新。生成语料库的过程比我从中获取数据源的过程要复杂得多,但我需要去往和来自这样的格式。这个问题阻止了我上面最早的解决方案,那就是如果有空白的字符串文档,阅读水平分数就会降低它们,我无法正确地映射出来并返回到tm。上面的'd'是我开始的对象。 – Mittenchops 2013-02-19 21:41:56

3

我对不起koRpus包不与TM封装互动是顺利呢。我一直在考虑如何在两个对象类之间翻译几个月,但还没有拿出一个真正令人满意的解决方案。如果你有这方面的想法,请不要犹豫与我联系。

但是,我想向您推荐由koRpus生成的可读性对象的summary()方法,该方法返回相关结果的精简data.frame。这可能比通过相当复杂的S4对象进行替代爬网要容易得多;-)您也可以尝试summary(x, flat=TRUE)

@agstudy:好图:-)为了节省一些时间,你应该在readability()之前运行hyphen(),所以你可以通过“连字符”参数重新使用结果。或者你可以简单地访问readability()结果后的“连字符”插槽。如果需要,它会自动连字,并保留结果。只有在下一步之前需要更改hyphen()的输出时,才需要手动调用连字符。我可能会补充说0.05-1是这个比它的前辈快得多

+1

我以前没有看到您的评论!我想你是'koRpus'软件包的作者。 +1! – agstudy 2013-11-28 16:54:54

2

作为qdap version 1.1.0,qdap具有number of functions是与TM包更相容。这里有一种方法可以使用您提供的相同Corpus(请注意,Fry最初是一种图形度量,而qdap保留了这一点;同样通过您的语料库和随机抽样,Fry建议您的样本语料库不够大,无法计算在弗莱的):

library(qdap) 
with(tm_corpus2df(d), flesch_kincaid(text, docs)) 

## docs word.count sentence.count syllable.count FK_grd.lvl FK_read.ease 
## 1 s1   33    1    54  16.6  34.904 
## 2 s2   49    1    75  21.6  27.610 

with(tm_corpus2df(d), fry(text, docs)) 

## To plot it 
qheat(with(tm_corpus2df(d), flesch_kincaid(text, docs)), values=TRUE, high="red") 

enter image description here

相关问题