2013-05-30 4 views
2

В R Я использовал [tm package][1] для создания матрицы терминов-документов из корпуса документов.findAssocs для нескольких терминов в R

Моя цель состоит в том, чтобы извлечь словарные ассоциации из все bigrams в терминологии матрицы документов и возврата для каждой тройки или некоторых. Поэтому я ищу переменную, которая содержит все строки.names из матрицы, поэтому функция findAssocs() может выполнять свою работу.

Это мой код до сих пор:

library(tm) 
library(RWeka) 
txtData <- read.csv("file.csv", header = T, sep = ",") 
txtCorpus <- Corpus(VectorSource(txtData$text)) 

...further preprocessing 

#Tokenizer for n-grams and passed on to the term-document matrix constructor 
BigramTokenizer <- function(x) NGramTokenizer(x, Weka_control(min = 2, max = 2)) 
txtTdmBi <- TermDocumentMatrix(txtCorpus, control = list(tokenize = BigramTokenizer)) 

#term argument holds two words since the BigramTokenizer extracted all pairs from txtCorpus 
findAssocs(txtTdmBi, "cat shop", 0.5) 
cat cabi cat scratch ... 
    0.96   0.91 

Я попытался определить переменную со всеми row.names из txtTdmBi и кормить его функции findAssocs(). Однако, со следующим результатом:

allRows <- c(row.names(txtTdmBi)) 
findAssocs(txtTdmBi, allRows, 0.5) 
Error in which(x[term, ] > corlimit) : subscript out of bounds 
In addition: Warning message: 
In term == Terms(x) : 
    longer object length is not a multiple of shorter object length 

Поскольку извлекая ассоциации на срок провел на несколько матриц терм-документе уже объяснил here, я думаю, можно было бы найти ассоциации для нескольких терминов в одном перспективе, матрица документов. Кроме того, как?

Я надеюсь, что кто-то может разъяснить мне, как это решить. Заранее благодарим за любую поддержку.

ответ

6

Если я правильно понял, решение lapply, вероятно, способ ответить на ваш вопрос. Это тот же подход, как и ответ, что Вы связываетесь, но вот самодостаточный пример, который мог бы быть ближе к прецеденту:

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

library(tm) 
library(RWeka) 
data(crude) 

Ваш биграмм токенизатор ...

#Tokenizer for n-grams and passed on to the term-document matrix constructor 
BigramTokenizer <- function(x) NGramTokenizer(x, Weka_control(min = 2, max = 2)) 
txtTdmBi <- TermDocumentMatrix(crude, control = list(tokenize = BigramTokenizer)) 

Убедитесь, что он работал путем проверки случайной выборки ...

inspect(txtTdmBi[1000:1005, 10:15]) 
A term-document matrix (6 terms, 6 documents) 

Non-/sparse entries: 1/35 
Sparsity   : 97% 
Maximal term length: 18 
Weighting   : term frequency (tf) 

        Docs 
Terms    248 273 349 352 353 368 
    for their   0 0 0 0 0 0 
    for west    0 0 0 0 0 0 
    forced it   0 0 0 0 0 0 
    forced to   0 0 0 0 0 0 
    forces trying  1 0 0 0 0 0 
    foreign investment 0 0 0 0 0 0 

Вот ответ на ваш вопрос:

Теперь используйте lapply функцию для вычисления связанных слов для каждого элемента вектора точки в матрице термина документа. Вектор термина наиболее просто доступен с txtTdmBi$dimnames$Terms. Например, txtTdmBi$dimnames$Terms[[1005]] - это «иностранные инвестиции».

Здесь я использовал llply из пакета plyr, поэтому у нас может быть индикатор выполнения (утешительный для больших заданий), но он в основном такой же, как и базовая функция lapply.

library(plyr) 
dat <- llply(txtTdmBi$dimnames$Terms, function(i) findAssocs(txtTdmBi, i, 0.5), .progress = "text") 

Выход список, где каждый элемент списка представляет собой вектор именованных чисел, где имя это термин, и число это значение корреляции.Например, чтобы увидеть условие, связанное с «иностранными инвестициями», мы можем получить доступ к списку как так:

dat[[1005]] 

и здесь термины, связанные с этим термином (я только что вставил в топе несколько)

168 million    1986 was   1987 early    300 mln    31 pct 
       1.00     1.00     1.00     1.00     1.00 
       a bit   a crossroads    a leading   a political   a population 
       1.00     1.00     1.00     1.00     1.00 
      a reduced    a series   a slightly   about zero activity continues 
       1.00     1.00     1.00     1.00     1.00 
     advisers are agricultural sector  agriculture the    all such   also reviews 
       1.00     1.00     1.00     1.00     1.00 
     and advisers   and attract   and imports  and liberalised    and steel 
       1.00     1.00     1.00     1.00     1.00 
      and trade   and virtual  announced since   appears to   are equally 
       1.00     1.00     1.00     1.00     1.00 
    are recommending    areas for    areas of     as it    as steps 
       1.00     1.00     1.00     1.00     1.00 
      asia with   asian member assesses indonesia   attract new   balance of 
       1.00     1.00     1.00     1.00     1.00 

Это то, что вы хотите сделать?

Кстати, если матрица терм-документ очень большой, вы можете попробовать эту версию findAssocs:

# u is a term document matrix 
# term is your term 
# corlimit is a value -1 to 1 

findAssocsBig <- function(u, term, corlimit){ 
    suppressWarnings(x.cor <- gamlr::corr(t(u[ !u$dimnames$Terms == term, ]),   
             as.matrix(t(u[ u$dimnames$Terms == term, ])) )) 
    x <- sort(round(x.cor[(x.cor[, term] > corlimit), ], 2), decreasing = TRUE) 
    return(x) 
} 

Это можно сделать следующим образом:

dat1 <- llply(txtTdmBi$dimnames$Terms, function(i) findAssocsBig(txtTdmBi, i, 0.5), .progress = "text") 

Преимущество это то, что он использует другой способ преобразования TDM в матрицу tm:findAssocs. Этот другой метод использует память более эффективно и поэтому предотвращает такое сообщение: Error: cannot allocate vector of size 1.9 Gb от происходящего.

Быстрый бенчмаркинга показывает, что обе findAssocs функции примерно с той же скоростью, так что главное различие заключается в использовании памяти:

library(microbenchmark) 
microbenchmark(
dat1 <- llply(txtTdmBi$dimnames$Terms, function(i) findAssocsBig(txtTdmBi, i, 0.5)), 
dat <- llply(txtTdmBi$dimnames$Terms, function(i) findAssocs(txtTdmBi, i, 0.5)), 
times = 10) 

Unit: seconds 
                        expr  min  lq median 
dat1 <- llply(txtTdmBi$dimnames$Terms, function(i) findAssocsBig(txtTdmBi,  i, 0.5)) 10.82369 11.03968 11.25492 
    dat <- llply(txtTdmBi$dimnames$Terms, function(i) findAssocs(txtTdmBi,  i, 0.5)) 10.70980 10.85640 11.14156 
     uq  max neval 
11.39326 11.89754 10 
11.18877 11.97978 10 
+0

Благодаря Бен! Мне удалось найти ассоциации для всех биграмм в моей терминологической матрице. Однако в переменной 'dat' я заменил' txtTdmBi $ dimnames $ Terms' на 'txtTdmBi', так как я продолжал получать ошибку:' 0% Ошибка в UseMethod ("findAssocs", x): не применяется применимый метод для 'findAssocs' к объекту класса «character» ' – Grote

+0

В дополнение к этой теме; функция 'findAssocsBig' в вашем примере - отличное решение для сохранения памяти. Как подать заявку на несколько терминов. Также подход 'lapply'? – Grote

+0

Благодарим за ошибку, я исправил свой ответ и добавил, как вы можете использовать другую функцию. – Ben

Смежные вопросы