2013-02-13 46 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