Un lematizador para el español con R… ¿cutre? ¿mejorable?

Uno de los pasos previos para realizar lo que se viene llamando minería de texto es lematizar el texto. Desafortunadamente, no existen buenos lematizadores en español. Al menos, buenos lematizadores libres.

Existen el llamado algoritmo de porter y snowball pero, o son demasiado crudos o están más pensados para un lenguaje con muchas menos variantes morfológicas que el español.

Sinceramente, no sé a qué se dedican —me consta que los hay— los lingüistas computacionales de la hispanidad entera: ¿no son capaces de liberar una herramienta de lematización medianamente decente que podamos usar los demás? Lo más parecido a esa herramienta aparentemente inexistente que conozco es Grampal, que funciona a través de una interfaz web.

Y me ha servido para construir un lematizador rudimentario y francamente perfectible:

require( XML )
 
lematiza <- function( frase ){
	palabra <- gsub( " ", "+", frase )
	base.url <- paste( 
             "http://cartago.lllf.uam.es/grampal/grampal.cgi?m=etiqueta&e=", 
             palabra, sep = "" )
	tmp <- readLines( base.url, encoding = 'utf8' )
	tmp <- iconv( tmp, "utf-8" )
	tmp <- gsub( "&nbsp;", " ", tmp )
	tmp <- readHTMLTable( tmp )
	tmp <- as.character( tmp[[1]]$V3 )
	tmp <- do.call( rbind, strsplit( tmp, " " ) )[,4]
	tmp
}

Con él, desde R,

> lematiza( "des" )
[1] "DAR"
> lematiza( "anduve" )
[1] "ANDAR"
> lematiza( "casitas" )
[1] "CASITA"
> lematiza( "comimos" )
[1] "COMER"
> lematiza( "queremos comer patatas" )
[1] "QUERER" "COMER"  "PATATA"

No es rapidísimo, debería mejorar el tratamiento de la codificación y muchas cosas más.

¿Se anima a mejorarlo alguno de mis lectores?

11 comentarios sobre “Un lematizador para el español con R… ¿cutre? ¿mejorable?

  1. Otto Wagner 13 diciembre, 2011 10:28

    Hola, desde mi desconocimiento en estos menesteres. ¿Qué utilidad tiene un lematizador?

    Gracias y saludos!

  2. Juanjo 13 diciembre, 2011 14:14

    Hola Otto:

    Pues, dicho muy burdamente, no repetir palabras en tus análisis. “anduve” y “andaba” tienen una misma raíz (lema), que es el verbo andar. No nos interesa conocer el tiempo verbal ni la persona, sino tan solo la acción que representan (el significado). (¿Algún lingüista que corrija esto que digo en la sala?).

    Saludos.

    Juanjo

    BTW: Stanford ha anunciado para enero de 2012 un curso gratis y online de Natural Language Processing. ¿Alguien se anima? http://www.nlp-class.org/

  3. Emilio 22 diciembre, 2011 0:54

    Sugiero utilizar un diccionario para realizar estos análisis sobre la marcha. En este fichero hay dos funciones:
    – lematizador: que busca en un diccionario local la palabra o palabras derivadas.
    – lematizadorGRAMPAL: consulta a la página web de GRAMPAL

    a <- url("http://uce.uniovi.es/mundor/lematizador.r&quot😉
    source(a)
    close(a)

    lista <- c("des", "anduve","casitas","comimos","queremos","patatas")
    system.time(k1 <- lapply(lista, lematizador))
    system.time(k2 <- lapply(lista, lematizadorGRAMPAL))
    unlist(k1)
    unlist(k2)

  4. datanalytics 22 diciembre, 2011 13:14

    @Emilio Tengo una versión “mejorada” del lematizadorGRAMPAL: te la pasaré.

    ¡Creo que esto está pidiendo a gritos un grupo de interés (SIG) de NLP en R!

  5. Emilio 4 enero, 2012 23:37

    No estaría mal que los expertos en NLP españoles trasladaran su saber a R, máxime cuando casi todos ellos trabajan con software libre…

    Dejo aquí un diccionario de sinónimos en Español.

    a <- url( "http://uce.uniovi.es/mundor/spthesaurus.rda&quot; )
    load(a)
    close(a)

    word <- "banco"

    topics <- unique(spthesaurus$topic[ spthesaurus$word == word])
    synonyms <- lapply(topics, function(x)
    droplevels(spthesaurus$word[spthesaurus$topic == x]))
    names(synonyms) <- topics
    synonyms

    Resultado:
    $alfaque
    [1] alfaque bajío escollo banco
    Levels: alfaque bajío banco escollo

    $banco
    [1] banco mesa asiento cárcel sotabanco faja
    [7] tira porción parcialidad bandada lado costado
    [13] banquillo
    13 Levels: asiento banco bandada banquillo cárcel costado faja lado … tira

    $bando
    [1] bando banco edicto mandato
    Levels: banco bando edicto mandato

    $banqueta
    [1] banqueta banquillo banco taburete asiento alzapiés escabel
    Levels: alzapiés asiento banco banqueta banquillo escabel taburete

    $banquete
    [1] banquete comilona festín convite
    [5] gaudeamus simposia (norae) banco ágape
    [9] banquillo
    9 Levels: ágape banco banquete banquillo comilona convite festín … simposia (norae)

  6. Rodrigo 18 febrero, 2013 15:54

    Hola.
    Hace poco me puse en contacto con el profesor Ingo Feinerer, desarrollador del paquete “tm” que permite realizar Text Mining en R.
    Le preguntaba sobre el proceso de “stemming” para el lenguaje español, lo cual es bastante bien realizado especificando el lenguaje al momento de generar el Corpus respectivo.
    Los detalles los pueden encontrar en la documentación y artículos escritos por Feinerer sobre “tm”.
    Les dejo una parte de sus respuesta sobre stemming para spanish language:

    That depends on the language. If you use the Porter stemming algorithm for English:

    R> SnowballStemmer(c(“actualiza”, “actualizada”, “actualizado”))
    [1] “actualiza” “actualizada” “actualizado”

    But it works if you set the correct language (Spanish):

    R> SnowballStemmer(c(“actualiza”, “actualizada”, “actualizado”),
    R> RWeka::Weka_control(S = “spanish”))
    [1] “actualiz” “actualiz” “actualiz”

    This is automatically done for you if you set the corpus language in tm. E.g.,

    Corpus(VectorSource(…), readerControl = list(language = “es”))

    See ?Corpus for details.

    > Same idea with “entrega y entregar”

    R> SnowballStemmer(c(“entrega”, “entregar”))
    [1] “entrega” “entregar”
    R> SnowballStemmer(c(“entrega”, “entregar”), RWeka::Weka_control(S =
    R> “spanish”))
    [1] “entreg” “entreg”

Los comentarios están desabilitados.