2013-02-13 9 views
6

Czy jest do tego gotowa funkcja w bibliotece tm, lub taka, która z nią ładnie gra?Jak obliczyć czytelność w R z pakietem tm

Mój obecny corpus jest ładowany do tm, coś w następujący sposób:

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

Próbowałem za pomocą koRpus, ale wydaje się głupie retokenize w innym opakowaniu niż ten już używam. Miałem także problemy z wektoryzowaniem obiektu zwracanego w sposób, który pozwoliłby mi ponownie wprowadzić wyniki do tm. (Mianowicie, z powodu błędów, często zwracał więcej lub mniej wyników czytelności niż liczba dokumentów w mojej kolekcji).

Rozumiem, że mogłem wykonać naiwne obliczenie analizujące samogłoski jako sylaby, ale chcę bardziej dokładnego pakietu, który zajmuje się już sprawami krawędziowymi (adres cichy, itp.).

Moje wyniki czytelności z wyboru to Flesch-Kincaid lub Fry.

Co Próbowałem pierwotnie gdzie d jest mój korpus 100 dokumentów:

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

Niestety x zwraca mniej niż 100 dokumentów, więc nie mogę skojarzyć sukcesy z odpowiednim dokumentem. (Jest to częściowo moje niezrozumienie "foreach" versus "lapply" w R, ale uznałem strukturę obiektu tekstowego za wystarczająco trudną, że nie mogłem się odpowiednio tokenizować, zastosować flesch.kincaid i skutecznie sprawdzać błędy w rozsądnej kolejności oświadczenia.)

UPDATE

Dwie inne rzeczy próbowałem, próbując zastosować funkcje KORPUS do obiektu tm ...

  1. przekazywać argumenty do obiektu tm_map, używając domyślny tokenizer: tm_map(d,flesch.kincaid,force.lang="en",tagger=tokenize)

  2. Zdefiniuj tokenizera, które przechodzą w

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

Obie te zwrócone.

Error: Specified file cannot be found: 

Następnie wymienia pełny tekst d [1]. Wydaje się, że to znalazłeś? Co powinienem zrobić, aby poprawnie przekazać funkcję?

UPDATE 2

Tutaj jest błąd pojawia się, gdy próbuję mapować funkcje KORPUS bezpośrednio z 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. 

To wygląda dziwnie błędu --- ja prawie nie sądzę oznacza to, że nie może zlokalizować tekstu, ale nie może znaleźć pustego kodu błędu (takiego jak "tokenizer"), zanim opuści umieszczony tekst.

UPDATE 3

Innym problemem zmieniać tagów pomocą koRpus zmieniać tagów, że (w przeciwieństwie do nadawania oznaczeń tm) był bardzo powolny, a jego wyjście atomizacja postęp na standardowe. Zresztą próbowałem następujące:

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

Moim zamiarem tutaj byłoby ponownie powiązać obiekt y nad powrotem do mojego tm(d) corpus jako metadane, meta(d, "F-KScore") <- y.

Niestety, zastosowane do mojego aktualnego zestawu danych, pojawia się komunikat o błędzie:

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

Myślę, że jednym z elementów mojego rzeczywistego corpus musi być NA, ani zbyt długi, coś innego i wygórowane --- z powodu zagnieżdżonej funkcjonalizacji, mam problem ze śledzeniem dokładnie, która jest.

Obecnie wygląda na to, że nie ma gotowej funkcji do odczytu wyników, które dobrze pasują do biblioteki tm. Dopóki ktoś nie zobaczy łatwego rozwiązania powodującego błąd, mógłbym połączyć się z moimi wezwaniami, by poradzić sobie z niezdolnością do tokenu niektórych pozornie błędnych, zniekształconych dokumentów?

+0

nie można użyć 'flesh.kincaid' od Korpus z' tm_map' z tm? –

+0

Nie mogę. Mówi "Błąd: nie podano żadnego języka!" dla każdej odmiany 'tm_map (dd, flesch.kincaid)' ja mogę myśleć, takich jak 'tm_map (dd, flesch.kincaid," en ")', itp. – Mittenchops

+0

Więc, skonsultowałem się z innym pytaniem SO (http://stackoverflow.com/questions/6827299/r-apply-function-with-multiple-parameters) o przekazywaniu argumentów do zagnieżdżonych funkcji. Próbowałem tego 'tm_map (d, flesch.kincaid, force.lang =" en ", tagger = tokenize)' ale dostaję błąd, że nie może znaleźć "określonego pliku", a następnie wyprowadza zawartość dokumentu 1. – Mittenchops

Odpowiedz

4

Otrzymujesz błąd, ponieważ funkcje koRpus nie mogą obsługiwać obiektu corpus. Lepiej jest utworzyć obiekt o numerze kRp.tagged, a następnie zastosować wszystkie dostępne na nim funkcje koRpus. Tutaj pokażę, jak to zrobię, używając pakietu danych tm.

Używam list.files, aby uzyskać listę plików źródłowych. Musisz tylko podać właściwą ścieżkę do plików tekstowych źródeł.

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

Potem skonstruować listę kRp.tagged obiekt za pomocą tokenize który jest domyślnym tagger podane z pakietem koRpus (Jest recommanded używać TreeTagger ale trzeba go instalować)

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

Raz Mam listę "oznaczonych" obiektów, na których mogę zastosować wzór czytelności. Od flesch.kincaid jest owinięcie z readability będę stosować bezpośrednio drugi:

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 

itp .... to wszystko tworzy listę obiektów S4. Gniazdo desc daje łatwy dostęp do tej listy:

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 

Można na przykład użyć gniazdo hyphen dostać ramkę danych z dwóch colums, WORD (te sprzężone słowa) i syll (liczba sylab) . tutaj, używając lattice, wiążę wszystkie dane.frames, aby wykreślić dotplot dla każdego dokumentu.

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

To jest piękna odpowiedź i pomocna, ale jeśli format, który mam nie jest przechowywany lokalnie, jak pliki tekstowe owidów, nadal nie rozumiem, jak tokenizować i powiązać go z obiektami tm. Użyłem tej biblioteki do innych analiz, więc nadal potrzebuję sposobu na wpisanie wyników czytelności KoRpus z powrotem do tych elementów, nawet jeśli całkowicie przełączam się na koRpus dla tego algo. – Mittenchops

+0

@Mittenchops dzięki! ok nie lokalnie, ale gdzie są? co masz na myśli, pobierając socres do tm .. jeśli wynik jest według dokumentu, łatwo jest umieścić go w swoich obiektach TM jako ** meta ** coś jak 'meta (doc [i], 'scoree') < - score' ... – agstudy

+0

Dzięki, @agstudy. Dodałem aktualizację powyżej. Proces tworzenia korpusu jest o wiele bardziej skomplikowany niż ze źródła danych, z którego go otrzymuję, ale muszę przejść do iz takiego formatu. Problemem uniemożliwiającym wcześniejsze rozwiązanie powyższego problemu było to, że jeśli istnieją puste dokumenty z ciągami znaków, wynik poziomu czytania po prostu je upuszcza i nie mogę poprawnie mapować z powrotem do Tm i z powrotem do niego. 'd' powyżej to obiekt, z którego zaczynam. – Mittenchops

3

Przepraszam pakiet KORPUS nie wchodzi w interakcje z pakietem tm, która płynnie jeszcze. Zastanawiam się nad sposobami, aby tłumaczyć między dwiema klasami obiektów od wielu miesięcy, ale jeszcze nie znalazłem satysfakcjonującego rozwiązania.Jeśli masz pomysły na to, nie wahaj się ze mną skontaktować.

Chciałbym jednak odnieść się do metody czytelności obiektów produkowanych przez koRpus, która zwraca skondensowane data.frame odpowiednich wyników. Jest to prawdopodobnie znacznie łatwiejszy dostęp niż alternatywne przeszukiwanie przez dość złożone obiekty S4 ;-) Możesz również spróbować summary(x, flat=TRUE).

@agstudy: Ładny wykres :-) Aby zaoszczędzić trochę czasu, należy uruchomić hyphen() przed readability(), aby ponownie wykorzystać wyniki za pomocą argumentu "łącznik". Możesz też po prostu uzyskać dostęp do "łącznika" z readability() wyników. W razie potrzeby rozdzieli automatycznie, i zachowa wyniki. Ręczne wywoływanie myślnika powinno być konieczne tylko wtedy, gdy przed kolejnymi krokami trzeba zmienić wyjście hyphen(). Mogę dodać, że 0.05-1 to znacznie szybciej w tym niż jego poprzednicy.

+1

Nie widziałem Twojego komentarza wcześniej! Domyślam się, że jesteś autorem pakietu 'koRpus'. +1! – agstudy

2

Począwszy od qdap version 1.1.0, qdap ma number of functions, aby być bardziej kompatybilny z pakietem TM. Oto sposób podejścia do problemu za pomocą tego samego dostarczonego przez ciebie Corpus (zauważ, że Fry był pierwotnie graficzną miarą i qdap to zachowuje, także za pomocą Twojego Corpus i losowego próbkowania Fry zasugerował, że twój próbny Corpus nie jest wystarczająco duży, aby obliczyć Fry Włączone):

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