Variabili locali all’interno di aes

Sto cercando di usare una variabile locale in aes quando ordino con ggplot. Questo è il mio problema ridotto all’essenza:

 xy <- data.frame(x=1:10,y=1:10) plotfunc <- function(Data,YMul=2){ ggplot(Data,aes(x=x,y=y*YMul))+geom_line() } plotfunc(xy) 

Ciò si traduce nel seguente errore:

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

Sembra come se non posso usare le variabili locali (o gli argomenti di funzione) in aes . Potrebbe essere che si verifichi a causa del contenuto di aes viene eseguito in un secondo momento quando la variabile locale è fuori portata? Come posso evitare questo problema (oltre a non usare la variabile locale all’interno di aes )?

Vorrei catturare l’ambiente locale,

 xy < - data.frame(x=1:10,y=1:10) plotfunc <- function(Data, YMul = 2){ .e <- environment() ggplot(Data, aes(x = x, y = y*YMul), environment = .e) + geom_line() } plotfunc(xy) 

Ecco un’alternativa che ti permette di passare qualsiasi valore attraverso l’argomento YMul senza doverlo aggiungere al Data data.frame o all’ambiente globale:

 plotfunc < - function(Data, YMul = 2){ eval(substitute( expr = { ggplot(Data,aes(x=x,y=y*YMul)) + geom_line() }, env = list(YMul=YMul))) } plotfunc(xy, YMul=100) 

Per vedere come funziona, prova la seguente riga in isolamento:

 substitute({ggplot(Data, aes(x=x, y=y*YMul))}, list(YMul=100)) 

ggplot() aspetta che YMul sia una variabile all’interno del frame di dati. Prova ad includere YMull lì invece:

Grazie a @Justin: ggplot() sembra cercare YMul nel frame dei dati e, se non trovato, nell’ambiente globale. Mi piace aggiungere tali variabili al frame dei dati, come segue, poiché ha senso per me concettualmente. Inoltre, non devo preoccuparmi delle modifiche alle variabili globali che hanno conseguenze impreviste sulle funzioni. Ma anche tutte le altre risposte sono corrette. Quindi, usa quello che fa per te.

 require("ggplot2") xy < - data.frame(x = 1:10, y = 1:10) xy <- cbind(xy, YMul = 2) ggplot(xy, aes(x = x, y = y * YMul)) + geom_line() 

Oppure, se vuoi la funzione nel tuo esempio:

 plotfunc < - function(Data, YMul = 2) { ggplot(cbind(Data, YMul), aes(x = x, y = y * YMul)) + geom_line() } plotfunc(xy) 

Sto usando ggplot2 e il tuo esempio sembra funzionare bene con la versione corrente.

Tuttavia, è facile trovare varianti che creano ancora problemi. Ero io stesso confuso da un comportamento simile, ed è così che ho trovato questo post (il miglior risultato di Google per “ggplot come valutare le variabili quando sono passate”). Ad esempio, se spostiamo ggplot da plotfunc:

 xy < - data.frame(x=1:10,y=1:10) plotfunc <- function(Data,YMul=2){ geom_line(aes(x=x,y=y*YMul)) } ggplot(xy)+plotfunc(xy) # Error in eval(expr, envir, enclos) : object 'YMul' not found 

Nella variante precedente, "catturare l'ambiente locale" non è una soluzione perché ggplot non è chiamato all'interno della funzione, e solo ggplot ha l'argomento "environment =".

Ma ora esiste una famiglia di funzioni "aes_", "aes_string", "aes_q" che sono come "aes" ma catturano variabili locali. Se usiamo "aes_" in quanto sopra, otteniamo ancora un errore perché ora non sa di "x". Ma è facile fare riferimento direttamente ai dati, il che risolve il problema:

 plotfunc < - function(Data,YMul=2){ geom_line(aes_(x=Data$x,y=Data$y*YMul)) } ggplot(xy)+plotfunc(xy) # works 

Hai esaminato la soluzione fornita da @wch (W. Chang)?

https://github.com/hadley/ggplot2/issues/743

Penso che sia il migliore

essenzialmente è come quello di @baptiste ma include il riferimento all’ambiente direttamente nella chiamata a ggplot

Lo riferisco qui

 g < - function() { foo3 <- 4 ggplot(mtcars, aes(x = wt + foo3, y = mpg), environment = environment()) + geom_point() } g() # Works 

Se si esegue il codice al di fuori della funzione funziona. E se si esegue il codice all’interno della funzione con YMul definito globalmente, funziona. Non capisco appieno il funzionamento interno di ggplot ma questo funziona …

 YMul < - 2 plotfunc <- function(Data){ ggplot(Data,aes(x=x,y=y*YMul))+geom_line() } plotfunc(xy)