Как рассчитать читаемость в 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]))

Я пробовал использовать koRpus, но кажется глупым ретокенизировать в другом пакете, чем тот, который я уже использую. У меня также были проблемы с векторизацией его возвращаемого объекта таким образом, чтобы я мог повторно включить результаты в tm. (А именно, из-за ошибок он часто возвращал больше или меньше оценок читабельности, чем количество документов в моей коллекции.)

Я понимаю, что мог бы выполнить наивный расчет, анализируя гласные как слоги, но мне нужен более тщательный пакет, который уже позаботится о крайних случаях (адрес молчаливых е и т. Д.).

Мои предпочтения по удобочитаемости - Флеш-Кинкейд или Фрай.

То, что я пробовал изначально, где 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 документов, поэтому я не могу связать успехи с правильным документом. (Отчасти это является моим неправильным пониманием «foreach» и «lapply» в R, но я обнаружил, что структура текстового объекта достаточно сложна, и я не мог надлежащим образом токенизировать, применять 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') перед сбросом обнаруженного текста .

ОБНОВЛЕНИЕ 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",])

Я намерен здесь повторно привязать объект 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. Если кто-то не увидит простое решение для поиска ошибок, я мог бы вставить свои вызовы функций, чтобы справиться с неспособностью токенизировать некоторые явно ошибочные, уродливые документы?


person Mittenchops    schedule 13.02.2013    source источник
comment
Разве вы не можете использовать flesh.kincaid от koRpus с tm_map от tm?   -  person Tyler Rinker    schedule 13.02.2013
comment
Кажется, я не могу. Он говорит: Ошибка: язык не указан! для всех возможных вариантов tm_map(dd,flesch.kincaid), таких как tm_map(dd,flesch.kincaid, "en") и т. д.   -  person Mittenchops    schedule 13.02.2013
comment
Итак, я проконсультировался с другим вопросом SO (stackoverflow. com / questions / 6827299 /) о том, как передавать аргументы во вложенные функции. Я пробовал это tm_map(d,flesch.kincaid,force.lang="en",tagger=tokenize), но получаю сообщение об ошибке, что указанный файл не может найти, а затем выводит содержимое документа 1.   -  person Mittenchops    schedule 13.02.2013


Ответы (3)


Вы получаете сообщение об ошибке, потому что koRpus функции не могут работать с corpus объектом. Лучше создать kRp.tagged объект, а затем применить к нему все koRpus функции. Здесь я покажу, как это сделать, используя ovid данные пакета tm.

Я использую list.files, чтобы получить список исходных файлов. Вам просто нужно указать правильный путь к исходным текстовым файлам.

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

Затем я создаю список объектов kRp.tagged, используя tokenize, который является теггером по умолчанию, заданным с пакетом koRpus (рекомендуется использовать TreeTagger, но вам необходимо его установить)

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

Когда у меня есть список «помеченных» объектов, я могу применить к нему формулу удобочитаемости. Поскольку 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

и т.д., .... все это создает список объектов 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, чтобы получить фрейм данных с двумя столбцами, словом (слова с переносом) и слогом (количество слогов). здесь, используя 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')))

введите описание изображения здесь

person agstudy    schedule 16.02.2013
comment
Это красивый и полезный ответ, но если формат, который у меня есть, не хранится локально, как текстовые файлы ovid, я все еще не понимаю, как выполнить токенизацию и связать ее с объектами tm. Я использовал эту библиотеку для других анализов, поэтому мне все еще нужен способ привязки оценок читабельности koRpus к этим объектам, даже если я полностью переключаюсь на koRpus для этого алгоритма. - person Mittenchops; 20.02.2013
comment
@Mittenchops, спасибо! ок нет локально, но где они? что вы имеете в виду, говоря о передаче socres в tm ... если оценка по документу, ее легко поместить в ваши tm-объекты как мета, что-то вроде _1 _... - person agstudy; 20.02.2013
comment
Спасибо, @agstudy. Я добавил обновление выше. Процесс создания корпуса намного сложнее, чем процесс из источника данных, из которого я его получаю, но мне нужно будет переходить в такой формат и обратно. Проблема, мешающая моему самому раннему решению, описанному выше, заключалась в том, что если есть пустые строковые документы, оценка уровня чтения просто снижает их, и я не могу правильно отобразить и вернуться в tm. d выше - это объект, с которого я начинаю. - person Mittenchops; 20.02.2013
comment
@Mittenchops Я все еще не понимаю, почему вы не можете сохранить свой d ‹- Corpus (VectorSource (stuff [, 1])) в файл, а затем действовать, как указано выше ..? - person agstudy; 20.02.2013
comment
Мне нужно будет проверить, умею ли я это делать. =) Могу ли я таким образом потерять свои метаданные? Я извлекал из файлов csv, поэтому раньше я не выполнял прямой ввод-вывод с tm. Казалось бы, чище, если это память, просто храните ее там, а не записывайте только для повторного чтения, верно? - person Mittenchops; 20.02.2013
comment
Теоретически да ... Но вы предполагаете, что эти 2 пакета должны работать согласованно ... может быть, вам нужно слишком много? это говорит, что вы можете сохранить в соединении (потоке). Я подробно расскажу об этом, если у меня будет больше времени .. - person agstudy; 20.02.2013

Мне очень жаль, что пакет koRpus еще не так гладко взаимодействует с пакетом tm. Я много месяцев думал о способах перевода между двумя классами объектов, но еще не нашел действительно удовлетворительного решения. Если у вас есть идеи для этого, не стесняйтесь обращаться ко мне.

Однако я хотел бы сослаться на метод summary() для объектов удобочитаемости, созданных koRpus, который возвращает сжатый data.frame соответствующих результатов. Это, вероятно, намного проще, чем альтернативный обход довольно сложных объектов S4 ;-) Вы также можете попробовать summary(x, flat=TRUE).

@agstudy: Хороший график :-) Чтобы сэкономить время, вы должны запустить hyphen() перед readability(), чтобы вы могли повторно использовать результаты с помощью аргумента «дефис». Или вы можете просто получить доступ к слоту «дефис» в readability() результатах. При необходимости он автоматически расставит дефис и сохранит результаты. Вызов дефиса вручную должен быть необходим только в том случае, если вам нужно изменить вывод hyphen() перед следующими шагами. Могу добавить, что 0,05–1 намного быстрее, чем его предшественники.

person m.eik    schedule 05.05.2013
comment
Я раньше не видел вашего комментария! Думаю, вы являетесь автором пакета koRpus. +1! - person agstudy; 28.11.2013

Начиная с qdap версии 1.1.0 qdap имеет количество функций, чтобы быть более совместимым с tm упаковка. Вот способ решения вашей проблемы, используя тот же Corpus, который вы предоставляете (обратите внимание, что Fry изначально был графической мерой, и qdap сохраняет это; также с помощью вашего корпуса и случайной выборки Фрай предположил, что ваш образец Corpus недостаточно велик для расчета Фрай идет):

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")

введите описание изображения здесь

person Tyler Rinker    schedule 28.02.2014