2014-07-07 4 views
6

Vorrei passare un frame di dati e le sue colonne per essere elaborate dal mutante di dplyr all'interno di una funzione.passaggio del frame di dati per mutare all'interno della funzione

Ecco un esempio

multifun <- function(dataf,vari){ 
mutate(dataf,newvar=vari*2) 
} 

multifun(mtcars,gear) 

Il problema con questa funzione è che il 'ingranaggio' variabile non è un oggetto riconosciuto. In particolare ho l'errore

Error in mutate_impl(.data, named_dots(...), environment()) 
object 'gear' not found 

Questo è un problema con l'ambiente in cui mutano di dplyr è alla ricerca per la variabile in questione.

Capisco che

multifun(mtcars,mtcars$gear) 

mi darà la risposta che voglio, e cioè

mpg cyl disp hp drat wt qsec vs am gear carb newvar 
1 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4  8 
2 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4  8 
3 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1  8 

ma vorrei vedere se c'è un modo per evitare la necessità di fare riferimento a ciascuna variabile utilizzato dal frame dati nella chiamata di funzione.

Sono anche consapevole del fatto che l'estrazione di Mute dalla funzione di chiamata funziona senza problemi. Vale a dire, mutate(mtcars,newvar=gear*2) fa il lavoro. Tuttavia, sto cercando di capire come il mutante di dplyr sta cercando la variabile in questione nei diversi ambienti quando è posizionata all'interno di una funzione.

Molte grazie in anticipo. robert

+0

Verificare se le soluzioni suggerite qui siano utili a tutti http: // StackOverflow.it/questions/21815060/dplyr-how-to-use-group-by-inside-a-function – konvas

risposta

4

Guardando soluzione @Anandas, questo sembra essere più semplice mod

multifun <- function(dataf, vari){ 
dataf <- mutate(dataf, newvar = dataf[, vari]*2); 
return(dataf) 
} 

multifun(mtcars,"gear") 

Anche in questo caso, prendendo incount @Anandas suggerimento, si potrebbe anche fare

multifun <- function(dataf, vari){ 
    vari <- deparse(substitute(vari)) 
    dataf <- mutate(dataf, newvar = dataf[, vari]*2) 
    return(dataf) 
} 

multifun(mtcars, gear) 
+1

È anche possibile aggiungere una riga 'vari <- deparse (sostituto (vari))' se si desidera utilizzare un valore non quotato come input per il secondo argomento. Non so se considererei questo un trucco. Per me è più leggibile del mio - stavo solo postando una risposta per vedere se mi ha aiutato a capire la parte 'error()' dell'errore. – A5C1D2H2I1M1N2O1R2T1

+0

Questo sembra davvero il più semplice. Tuttavia sembra che tutte le soluzioni risultino in un codice dettagliato se invece di avere una variabile ne abbiamo molte o se queste variabili appaiono in un codice complesso. Grazie comunque per tutte le risposte. – Robert

+0

Sembra quindi che se il codice è complesso o coinvolge molte variabili dal frame di dati, la soluzione meno verbosa potrebbe essere quella di specificare l'origine delle variabili nella chiamata di funzione come sopra indicato, ad esempio 'multifun (mtcars, mtcars $ gear) ', o chiaramente" hard coding "la variabile gear nella definizione della funzione come in [this] (http://stackoverflow.com/questions/24459752/can-dplyr-package-be-used-for-conditional-mutating?rq = 1) post – Robert

4

Questo è davvero brutto per me, ma sembra funzionare. Fondamentalmente, ho provato a usare get ma non sembrava sapere dove guardare, quindi ho specificato l'ambiente.

multifun <- function(dataf, vari){ 
    vari <- deparse(substitute(vari)) 
    mutate(dataf, newvar = get(vari, envir = as.environment(dataf)) * 2) 
} 

uscita:

multifun(mtcars, gear) 
#      mpg cyl disp hp drat wt qsec vs am gear carb newvar 
# Mazda RX4   21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4  8 
# Mazda RX4 Wag  21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4  8 
# Datsun 710   22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1  8 
# <<<SNIP>>> 
# Ferrari Dino  19.7 6 145.0 175 3.62 2.770 15.50 0 1 5 6  10 
# Maserati Bora  15.0 8 301.0 335 3.54 3.570 14.60 0 1 5 8  10 
# Volvo 142E   21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2  8 
2

oppure

multifun1 <- function(dataf, vari){ 
eval(substitute(mutate(dataf, newvar=vari*2), list(vari=as.name(vari)))) 
} 

multifun1(mtcars,"gear") 

Per utilizzare unquoted valore, sarebbe meglio usare il suggerimento di @Ananda Mahto

multifun1 <- function(dataf, vari){ 
vari <- deparse(substitute(vari)) 
eval(substitute(mutate(dataf, newvar=vari*2), list(vari=as.name(vari)))) 
} 

multifun1(mtcars,gear) 
+0

Sì. Funziona così. Notate che sia nella vostra risposta che nel mio post ho leggermente modificato il codice dal momento dell'assunzione di dataf <- e quindi restituirlo era ridondante. Grazie. – Robert

+0

@Robert. Grazie per il montaggio. L'ho notato ma ho dimenticato di modificare. – akrun

1

Con dplyr 0.7.0, questo può ora essere fatto con tidyeval:

multifun <- function(dataf,vari){ 
    mutate(dataf,newvar = UQ(enquo(vari))*2) 
} 

multifun(mtcars,gear) 

enquo citazioni dagli simbolo che fa riferimento all'argomento della funzione e lo raggruppa con l'ambiente in cui la funzione viene chiamata in una query. UQ o !! possono quindi essere utilizzati per annullare l'interrogazione del quench e valutarlo immediatamente entro mutate.