2011-08-31 18 views
7

Chcę stemplować dokumenty w Corpus of plain text documents przy użyciu pakietu TM w R. Kiedy stosuję funkcję SnowballStemmer do wszystkich dokumentów korpusu, tylko ostatnie słowo każdego dokumentu jest wynikało.Snowball Stemmer wywodzi tylko ostatnie słowo

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 

Myślę, że jest to związane ze sposobem wczytywania dokumentów do korpusu. Aby zilustrować to z kilku prostych przykładach:

> 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 
+0

Czy Rstem nie jest interfejsem R do Snowballa? Dlatego powinieneś bibliotekować (Rstem) i wypróbować tm_map (corp, wordStem). –

+0

Dzięki za komentarz. Próbowałem, a wyniki były takie same. Podam lepszy przykład powyżej, aby zilustrować problem nieco więcej. – Christian

Odpowiedz

3

Problem widzę jest to, że wordStem trwa w wektorze słów ale Corpus plainTextReader zakłada, że ​​w dokumentach, że czyta, każde słowo jest na osobnej linii. Innymi słowy, będzie to mylić plainTextReader jak skończy się z 3 „słów” w dokumencie

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

Zamiast dokument powinien być

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

Należy również zauważyć, że znaki interpunkcyjne myli również wordStem tak musiałbyś je również wyjąć.

Innym sposobem wykonania tej czynności bez modyfikowania rzeczywistych dokumentów jest zdefiniowanie funkcji, która umożliwiłaby separację i usunięcie znaków niebędących alfanumerycznymi, które pojawiają się przed słowem lub po nim. Oto prosty:

Teraz użyj korpB jako zwykłego Korpusu.

+0

Dzięki, efekt zadziałał. Jednak wyniki stosowania wordStem i SnowballStemmer są indywidualnymi wektorami znaków. Powoduje to problem polegający na tym, że funkcja DocumentTermMatrix nie działa już na wynikowym korpusie. Jak mogę to uruchomić? – Christian

+0

@ Christiana Edytowałem moją odpowiedź na to. Jeśli jest łatwiejszy sposób, nie wiem. –

4

obciążenia wymagane biblioteki

library(tm) 
library(Snowball) 

tworzą wektor

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

utworzyć korpus z wektorem

vec<-Corpus(VectorSource(vec)) 

bardzo ważną rzeczą jest, aby sprawdzić klasę naszego korpusu i zachować je jak chcemy standardowy korpus, który R funkcje rozumie

class(vec[[1]]) 

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

będzie to prawdopodobnie powiedzieć zwykły dokument tekstowy

Więc teraz możemy modyfikować naszą wadliwą funkcję stemDocument. najpierw przekształcamy nasz zwykły tekst w postać, a następnie dzielimy tekst, stosujemy stemDocument, który teraz działa dobrze i wkleja go ponownie. co najważniejsze, konwertujemy dane wyjściowe na PlainTextDocument podane przez pakiet tm.

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

teraz możemy użyć standardowego tm_map na naszej corpus

vec1 = tm_map(vec, stemDocumentfix) 

wynik jest

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

Najważniejszą rzeczą, którą musisz pamiętać jest presever klasę dokumentów w korpusie zawsze. Mam nadzieję, że jest to uproszczone rozwiązanie problemu przy użyciu funkcji z 2 załadowanych bibliotek.

Powiązane problemy