Pregunta

He intentado utilizar acast de reshape2 dentro de una función de auto por escrito, pero tenía el problema de que ACAST No se encontró los datos que se envíen a la misma.

Aquí está mi datos:

library("reshape2")
x <- data.frame(1:3, rnorm(3), rnorm(3), rnorm(3))    
colnames(x) <- c("id", "var1", "var2", "var3")
y <-melt(x, id = "id", measure = c("var1", "var2", "var3"))

y tendrá el aspecto siguiente:

  id variable      value
1  1     var1  0.1560812
2  2     var1  1.0343844
3  3     var1 -1.4157728
4  1     var2  0.8808935
5  2     var2  0.1719239
6  3     var2  0.6723758
7  1     var3 -0.7589631
8  2     var3  1.1325995
9  3     var3 -1.5744876

Ahora puede lanzar de nuevo a través de acast:

> acast(y,y[,1] ~ y[,2])
        var1      var2       var3
1  0.1560812 0.8808935 -0.7589631
2  1.0343844 0.1719239  1.1325995
3 -1.4157728 0.6723758 -1.5744876

Sin embargo, al escribir un pequeño envoltorio para acast que debería hacer lo mismo, aparece un mensaje de error estúpida:

wrap.acast <- function(dat, v1 = 1, v2 = 2) {
    out <- acast(dat, dat[,v1] ~ dat[,v2])
    return(out)
}

wrap.acast(y)

Error in eval(expr, envir, enclos) : object 'dat' not found

El problema está obviamente relacionado con algo así como entornos y variables globales / locales. Ya que da otros mensajes de error después de declarar dat en el entorno global (es decir, v1 y v2 no encontraron siempre y cuando no son global).

Me gustaría utilizar resahpe (especialmente ACAST) dentro de una función sin necesidad de declarar las variables fuera de la función. ¿Cuál es el truco?

Gracias.

¿Fue útil?

Solución

En lugar de utilizar la especificación fórmula, utilizar la especificación carácter:

acast(y, list(names(y)[1], names(y)[2]))

Otros consejos

Una cuestión es que está abusando la notación fórmula en R. Usted no debe hacer cosas como

> acast(y, y[,1] ~ y[,2])
        var1       var2         var3
1  2.1726117  0.6107264  0.291446236
2  0.4755095 -0.9340976 -0.443291873
3 -0.7099464 -1.2536334  0.001105352

como los bits 'Y' son redundantes si se suministra un objeto de datos. Si se refiere a las variables de y por el nombre directamente en la fórmula, las cosas funcionan muy bien

> acast(y, id ~ variable)
        var1       var2         var3
1  2.1726117  0.6107264  0.291446236
2  0.4755095 -0.9340976 -0.443291873
3 -0.7099464 -1.2536334  0.001105352

y el código es mucho más fácil de leer en esta segunda versión.

Para hacer lo que quiera usar el envoltorio acast se va a implicar la generación de la fórmula correcta utilizando el names, como señala Joris, y solución de Hadley es mucho más simple. Así que mi punto realmente es a tener en cuenta con la forma en que utiliza la especificación fórmula en R. Se ahorrará un montón de problemas en el largo plazo (aunque no específicamente con este problema en particular) si se utiliza fórmulas correctamente.

Corrección: problema no es que no encuentra dat, pero que no encuentra dat [v1] y dat [, v2] en la fórmula especificada. ACast toma un argumento de la fórmula tipo, y que uno se evaluó en un entorno temporal creado en torno a su trama de datos. Dentro de ese entorno, que no encuentra un "dat" objeto cuando la función se envuelve dentro de otro.

No estoy completamente después de cómo esto funciona en el global y no esté envuelto, pero si usted alimenta ACAST una fórmula, que funciona dentro de una función también.

wrap.acast <- function(dat, v1 = 1, v2 = 2) {
    x1 <- names(dat)[v1]
    x2 <- names(dat)[v2]
    form <- as.formula(paste(x1,"~",x2))
    out <- acast(dat,form)
    return(out)
}

utilizando sus datos de juguete:

> wrap.acast(y)
        var1      var2       var3
1 0.04095337 0.4044572 -0.4532233
2 1.23905358 1.2493187  0.7083557
3 0.72798307 0.7868746  1.7144811

He encontrado una manera bastante poco elegante de resolver el problema con las asignaciones de super (<<-).
Cambio de la función para la siguiente hace el trabajo. Sin embargo, es bastante feo, ya que crea las variables globales que permanecen.

wrap.acast <- function(dat, v1 = 1, v2 = 2) {
    dat <<- dat
    v1 <<- v1
    v2 <<- v2
    out <- acast(dat, dat[,v1] ~ dat[,v2])
    return(out)
}

Todavía estoy muy interesado en otras soluciones (menos de obstrucción).

antes de ejecutar la función:

> ls()
[1] "wrap.acast" "x"          "y"     

después de ejecutar la función:

> ls()
[1] "dat"        "v1"         "v2"         "wrap.acast" "x"         
[6] "y" 
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top