Снежок Стеммер только связан последним словом - PullRequest
7 голосов
/ 01 сентября 2011

Я хочу объединить документы в корпус текстовых документов, используя пакет tm в R. Когда я применяю функцию SnowballStemmer ко всем документам корпуса, используется только последнее слово каждого документа.

library(tm)
library(Snowball)
library(RWeka)
library(rJava)
path <- c("C:/path/to/diretory")
corp <- Corpus(DirSource(path),
               readerControl = list(reader = readPlain, language = "en_US",
                                    load = TRUE))
tm_map(corp,SnowballStemmer) #stemDocument has the same problem

Я думаю, это связано с тем, как документы читаются в корпус.Чтобы проиллюстрировать это на нескольких простых примерах:

> vec<-c("running runner runs","happyness happies")
> stemDocument(vec) 
   [1] "running runner run" "happyness happi" 

> vec2<-c("running","runner","runs","happyness","happies")
> stemDocument(vec2)
   [1] "run"    "runner" "run"    "happy"  "happi" <- 

> corp<-Corpus(VectorSource(vec))
> corp<-tm_map(corp, stemDocument)
> inspect(corp)
   A corpus with 2 text documents

   The metadata consists of 2 tag-value pairs and a data frame
   Available tags are:
     create_date creator 
   Available variables in the data frame are:
     MetaID 

   [[1]]
   run runner run

   [[2]]
   happy happi

> corp2<-Corpus(DirSource(path),readerControl=list(reader=readPlain,language="en_US" ,  load=T))
> corp2<-tm_map(corp2, stemDocument)
> inspect(corp2)
   A corpus with 2 text documents

   The metadata consists of 2 tag-value pairs and a data frame
     Available tags are:
     create_date creator 
   Available variables in the data frame are:
     MetaID 

   $`1.txt`
   running runner runs

   $`2.txt`
   happyness happies

Ответы [ 2 ]

4 голосов
/ 22 августа 2014

загрузка необходимых библиотек

library(tm)
library(Snowball)

создать вектор

vec<-c("running runner runs","happyness happies")

создать корпус из вектора

vec<-Corpus(VectorSource(vec))

очень важно проверить класс нашего корпуса и сохранить его так, как нам нужен стандартный корпус, который понимают функции R

class(vec[[1]])

vec[[1]]
<<PlainTextDocument (metadata: 7)>>
running runner runs

это, вероятно, скажет вам простой текстовый документ

Так что теперь мы модифицируем нашу неисправную функцию stemDocument. сначала мы конвертируем наш простой текст в символ, а затем разбиваем текст, применяем stemDocument, который теперь работает нормально, и вставляем его вместе самое главное, мы конвертируем вывод в PlainTextDocument, заданный пакетом tm.

stemDocumentfix <- function(x)
{
    PlainTextDocument(paste(stemDocument(unlist(strsplit(as.character(x), " "))),collapse=' '))
}

теперь мы можем использовать стандартное tm_map в нашем корпусе

vec1 = tm_map(vec, stemDocumentfix)

результат

vec1[[1]]
<<PlainTextDocument (metadata: 7)>>
run runner run

Самое важное, что вам нужно помнить, - это всегда сохранять класс документов в корпусе всегда. Я надеюсь, что это упрощенное решение вашей проблемы с использованием функции из двух загруженных библиотек.

3 голосов
/ 05 сентября 2011

Проблема, которую я вижу, состоит в том, что wordStem принимает вектор слов, а Corpus plainTextReader предполагает, что в документах, которые он читает, каждое слово находится на отдельной строке. Другими словами, это может сбить с толку plainTextReader, так как в вашем документе будет 3 слова "

From ancient grudge break to new mutiny,
Where civil blood makes civil hands unclean.
From forth the fatal loins of these two foes

Вместо этого документ должен быть

From
ancient
grudge
break
to
new
mutiny
where 
civil
...etc...

Обратите внимание, что пунктуация также сбивает с толку wordStem , поэтому вам также придется их убрать.

Еще один способ сделать это без изменения ваших фактических документов - определить функцию, которая будет выполнять разделение и удалять не алфавитно-цифровые символы, которые появляются перед или после слова. Вот простой:

wordStem2 <- function(x) {
    mywords <- unlist(strsplit(x, " "))
    mycleanwords <- gsub("^\\W+|\\W+$", "", mywords, perl=T)
    mycleanwords <- mycleanwords[mycleanwords != ""]
    wordStem(mycleanwords)
}

corpA <- tm_map(mycorpus, wordStem2);
corpB <- Corpus(VectorSource(corpA));

Теперь просто используйте corpB как обычный корпус.

...