2010-09-22 8 views
6

Ho provato a utilizzare acast da reshape2 all'interno di una funzione autodidatta, ma ho riscontrato il problema che acast non ha trovato i dati che gli ho inviato.Come usare acast (reshape2) all'interno di una funzione in R?

Ecco il mio dati:

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 allora assomiglia a questo:

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 

ora posso lanciarlo di nuovo via 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 

Tuttavia, quando si scrive un piccolo involucro per acast che dovrebbe fare lo stesso, ottengo uno stupido messaggi di errore:

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 

Il problema è ovviamente correlato a qualcosa come ambienti e variabili globali/locali. Come fornisce altri messaggi di errore dopo la dichiarazione di dat nell'ambiente globale (ad esempio, v1 e v2 non trovato finché non sono globali).

desidero utilizzare resahpe (specialmente ACAST) all'interno di una funzione senza la necessità di dichiarare variabili all'esterno della funzione. Qual è il trucco?

Grazie.

+0

Questo è un problema che si verifica più spesso negli ultimi tempi. Originariamente ho trovato che fosse un problema con i metodi S4, ma a quanto pare può verificarsi anche con altre funzioni. Questo è presumibilmente un bug in R, vedi anche le risposte a questa domanda: http://stackoverflow.com/questions/3574858/values-not-being-copied-to-the-next-local-environment/ –

+0

Grazie Joris. Ma ora ho l'impressione che non ci sia una soluzione facile al mio problema. non troppo bello ... – Henrik

+0

Appena scoperto ce n'è uno in realtà. È una questione di corretto typecasting. –

risposta

5

Invece di utilizzare la specifica formula, utilizzare la specifica carattere:

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

Questo è ancora più semplice. Grazie molto. E ancora più grazie per aver fornito reshape2 e tutti i tuoi fantastici pacchetti! – Henrik

2

Correzione: il problema non è che non trova dat, ma che non trova dat [, v1] e dat [, v2] nella formula specificata. Acast accetta un argomento con la formula del tipo e viene valutato in un ambiente temporaneo creato attorno al frame dei dati. All'interno di quell'ambiente, non trova un oggetto "dat" quando la funzione è racchiusa in un'altra.

Non sto seguendo completamente come funziona nel globale e non quando viene eseguito il wrapping, ma se si alimenta una formula, funziona anche all'interno di una funzione.

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

utilizzando i dati di giocattoli:

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

Questo è quello che volevo. Molte grazie. – Henrik

-2

ho trovato un modo abbastanza poco elegante per risolvere il problema utilizzando le assegnazioni super (<<-).
La modifica della funzione a quanto segue fa il lavoro. Ma è piuttosto brutto in quanto crea variabili globali che rimangono.

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

Sono ancora molto interessato ad altre soluzioni (meno intasamento).

prima di eseguire la funzione:

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

dopo l'esecuzione della funzione:

> ls() 
[1] "dat"  "v1"   "v2"   "wrap.acast" "x"   
[6] "y" 
+0

Come ti sei notato, l'uso di super assegnazioni dovrebbe essere evitato in ogni momento, a meno che tu non voglia veramente fare una variabile globale. E anche allora potresti voler ripensare al problema ... –

4

Un problema è che stai abusando della notazione formula in R. Non dovresti fare cose come

> 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 

poiché i bit "y" sono ridondanti se viene fornito un oggetto dati. Se si fa riferimento alle variabili di y per nome direttamente nella formula, le cose funzionano bene

> 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 

e il codice è molto più leggibile in questa seconda versione.

di fare ciò che si desidera utilizzare l'involucro acast sta per coinvolgere la generazione la formula corretta utilizzando l'names, come sottolinea Joris fuori, e la soluzione di Hadley è molto più semplice. Quindi il mio punto è davvero quello di stare attenti a come si usano le specifiche delle formule in R. Risolvi molti problemi a lungo termine (anche se non specificamente con questo particolare problema) se usi correttamente le formule.

Problemi correlati