如何使用tm包计算R中的可读性

Mit*_*ops 6 nlp r tm

库中是否有预先构建的功能tm,或者可以很好地使用它?

我当前的语料库被加载到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]))
Run Code Online (Sandbox Code Playgroud)

我尝试使用koRpus,但是在与我已经使用的包中不同的包中重新标记似乎很愚蠢.我也有问题以一种允许我将结果重新纳入其中的方式对其返回对象进行矢量化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]]))
Run Code Online (Sandbox Code Playgroud)

不幸的是,x返回少于100个文档,因此我无法将成功与正确的文档相关联.(这部分是我对R中'foreach'与'lapply'的误解,但我发现文本对象的结构足够困难,我无法正确地标记,应用flesch.kincaid,并以合理的顺序成功检查错误声明.)

UPDATE

我试过的另外两件事,试图将koRpus函数应用于tm对象......

  1. 使用默认的tokenizer将参数传递给tm_map对象: tm_map(d,flesch.kincaid,force.lang="en",tagger=tokenize)

  2. 定义一个tokenizer,传入它.

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

这两个都返回了:

   Error: Specified file cannot be found:
Run Code Online (Sandbox Code Playgroud)

然后列出d [ 1 ]的全文.好像找到了吗?我该怎么做才能正确传递函数?

更新2

这是我尝试使用lapply直接映射koRpus函数时得到的错误:

> 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. 
Run Code Online (Sandbox Code Playgroud)

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

更新3

使用重新标记的另一个问题koRpus是,重新标记(与tm标记符相比)非常慢,并将其标记化进度输出到标准输出.无论如何,我尝试过以下方法:

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",])
Run Code Online (Sandbox Code Playgroud)

我的意图是将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"
Run Code Online (Sandbox Code Playgroud)

我认为我的实际语料库中的一个元素必须是NA,或者太长,还有其他令人望而却步的元素 - 由于嵌套的功能化,我无法准确地追踪它是什么.

因此,目前看起来没有预先构建的功能来读取与tm图书馆很好地协作的分数.除非有人看到一个简单的错误捕获解决方案,否则我可以将其置于函数调用中以处理无法对某些明显错误的格式错误的文档进行标记的问题?

ags*_*udy 4

您会收到错误,因为koRpus函数无法处理corpus对象。最好创建一个kRp.tagged对象,然后在其上应用所有 koRpus功能。在这里我将展示如何使用包ovid的数据来做到这一点tm

我用来list.files获取源文件列表。您只需为源文本文件提供正确的路径即可。

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

kRp.tagged然后我构建一个对象列表,使用tokenize它是包中给出的默认标记器koRpus(建议使用TreeTagger,但您需要安装它)

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

一旦我有了“标记”对象的列表,我就可以对其应用可读性公式。由于flesch.kincaid是 的包装readability,我将直接应用后者:

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
Run Code Online (Sandbox Code Playgroud)

等等,......所有这些都会产生一个 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 
Run Code Online (Sandbox Code Playgroud)

例如,您可以使用槽hyphen来获取具有两列的数据框,即单词(连字符连接的单词)和音节(音节数)。在这里,我使用lattice绑定所有 data.frames,dotplot为每个文档绘制 a 。

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')))
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述