2010-03-11 20 views
7

Me gustaría escribir una función R que acepte una fórmula como primer argumento, similar a lm() o glm() y amigos. En este caso, se trata de una función que toma una trama de datos y escribe un archivo en SVMLight formato, que tiene esta forma general:Extraer información de la fórmula condicional

<line> .=. <target> <feature>:<value> <feature>:<value> ... <feature>:<value> # <info> 
<target> .=. +1 | -1 | 0 | <float> 
<feature> .=. <integer> | "qid" 
<value> .=. <float> 
<info> .=. <string> 

por ejemplo, la siguiente trama de datos:

result qid  f1  f2  f3  f4 f5  f6  f7  f8 
1  -1 1 0.0000 0.1253 0.0000 0.1017 0.00 0.0000 0.0000 0.9999 
2  -1 1 0.0098 0.0000 0.0000 0.0000 0.00 0.0316 0.0000 0.3661 
3  1 1 0.0000 0.0000 0.1941 0.0000 0.00 0.0000 0.0509 0.0000 
4  -1 2 0.0000 0.2863 0.0948 0.0000 0.34 0.0000 0.7428 0.0608 
5  1 2 0.0000 0.0000 0.0000 0.4347 0.00 0.0000 0.9539 0.0000 
6  1 2 0.0000 0.7282 0.9087 0.0000 0.00 0.0000 0.0000 0.0355 

haría ser representados de la siguiente manera:

-1 qid:1 2:0.1253 4:0.1017 8:0.9999 
-1 qid:1 1:0.0098 6:0.0316 8:0.3661 
1 qid:1 3:0.1941 7:0.0509 
-1 qid:2 2:0.2863 3:0.0948 5:0.3400 7:0.7428 8:0.0608 
1 qid:2 4:0.4347 7:0.9539 
1 qid:2 2:0.7282 3:0.9087 8:0.0355 

La función me gustaría escribir se llamaría algo así:

write.svmlight(result ~ f1+f2+f3+f4+f5+f6+f7+f8 | qid, data=mydata, file="out.txt") 

O incluso

write.svmlight(result ~ . | qid, data=mydata, file="out.txt") 

Pero no puedo encontrar la manera de utilizar model.matrix() y/o model.frame() saber qué columnas se supone que debe escribir. ¿Son estas las cosas correctas para mirar?

Cualquier ayuda muy apreciada!

Respuesta

4

Respuesta parcial. Puede subíndice un objeto fórmula para obtener un árbol de análisis sintáctico de la fórmula:

> f<-a~b+c|d 
> f[[1]] 
`~` 
> f[[2]] 
a 
> f[[3]] 
b + c | d 
> f[[3]][[1]] 
`|` 
> f[[3]][[2]] 
b + c 
> f[[3]][[3]] 
d 

Ahora todo lo que necesita es el código para recorrer este árbol.

ACTUALIZACIÓN: Aquí hay un ejemplo de una función que recorre el árbol.

walker<-function(formu){ 
    if (!is(formu,"formula")) 
    stop("Want formula") 
    lhs <- formu[[2]] 
    formu <- formu[[3]] 

    if (formu[[1]]!='|') 
    stop("Want conditional part") 

    condi <- formu[[3]] 

    flattener <- function(f) {if (length(f)<3) return(f); 
          c(Recall(f[[2]]),Recall(f[[3]]))} 
    vars <- flattener(formu[[2]]) 

    list(lhs=lhs,condi=condi,vars=vars) 
} 

walker(y~a+b|c) 

también un vistazo a la documentación de terms.formula y terms.object. Ver el código de algunas funciones que toman fórmulas condicionales puede ayudar, por ej. la función lmer en el paquete lme4.

+0

Heh - sí, caminar por el árbol es de hecho "todo lo que necesito". =) He echado un vistazo a lmer(), pero necesitaría tomar el paquete fuente porque su método 'lmerFrames()', que parece hacer el análisis sintáctico, está oculto. ¿O hay una forma de ver el código para los métodos S4 como este? –

+0

OK, mirando la fuente de 'lmerFrames()' etc. ahora. Qué asco. Supongo que siempre asumí que había una forma más astuta de manipular fórmulas. –

+1

Puede referirse a funciones no exportadas en espacios de nombres utilizando :::, por ej. lme4 ::: lmerFrames. Actualicé mi respuesta para incluir una función para recorrer el árbol, no hago mucha comprobación de entrada en este momento. –

Cuestiones relacionadas