2011-08-31 12 views
7

Quiero detener los documentos en un Corpus de documentos de texto sin formato con el paquete tm en R. Cuando aplico la función SnowballStemmer a todos los documentos del corpus, solo la última palabra de cada documento es derivadoSnowball Stemmer solo se deriva de la última palabra

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 

Creo que está relacionado con la forma en que se leen los documentos en el corpus. Para ilustrar esto con algunos ejemplos sencillos:

> 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

¿No es Rstem la interfaz R de Snowball? Por lo tanto, debe library (Rstem) y probar tm_map (corp, wordStem). –

+0

Gracias por el comentario. Lo intenté y los resultados fueron los mismos. Incluiré un mejor ejemplo anterior para ilustrar el problema un poco más. – Christian

Respuesta

3

El problema que veo es que wordStem toma en un vector de palabras sino Corpus plainTextReader asume que en los documentos que se lea, cada palabra es en su propia línea. En otras palabras, esto podría confundir plainTextReader a medida que va a terminar con "palabras" 3 en su documento

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

En cambio, el documento debe ser

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

Tenga en cuenta también que la puntuacion también confunde wordStem por lo tendrías que sacarlos también.

Otra forma de hacerlo sin modificar sus documentos reales es definir una función que haría la separación y eliminar los caracteres no alfanuméricos que aparecen antes o después de una palabra. Aquí hay uno simple:

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

Ahora solo use corpB como su Corpus habitual.

+0

Gracias, la raíz funcionó ahora. Sin embargo, los resultados de la aplicación de wordStem y SnowballStemmer son vectores de caracteres individuales. Esto da como resultado el problema de que la función DocumentTermMatrix ya no funciona en el corpus resultante. ¿Cómo podría hacer que esto funcione? – Christian

+0

@Christian He editado mi respuesta para esto. Si hay una manera más fácil, no lo sé. –

4

bibliotecas de carga requerida

library(tm) 
library(Snowball) 

crear vector

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

crean corpus a partir del vector

vec<-Corpus(VectorSource(vec)) 

cosa muy importante es comprobar la clase de nuestro corpus y preservarlo como queremos un corpus estándar que las funciones R entienden

class(vec[[1]]) 

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

esto probablemente le dirá documento de texto

Así que ahora modificamos nuestra función stemDocument defectuoso. primero convertimos nuestro texto plano a carácter y luego dividimos el texto, aplicamos stemDocument que funciona bien ahora y lo pegamos de nuevo. lo más importante es que reconvertimos la salida a PlainTextDocument dada por el paquete tm.

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

Ahora podemos usar tm_map estándar en nuestro corpus

vec1 = tm_map(vec, stemDocumentfix) 

resultado es

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

Lo más importante que debe recordar es presever clase de documentos en el corpus siempre. Espero que esta sea una solución simplificada para su problema al usar la función dentro de las 2 bibliotecas cargadas.

Cuestiones relacionadas