2014-10-21 11 views
18

Voglio passare arrange() {dplyr} un vettore di nomi di variabili su cui ordinare. Di solito scrivo solo le variabili che voglio, ma sto cercando di creare una funzione in cui le variabili di ordinamento possano essere inserite come parametro di funzione.Passare un vettore di nomi di variabili per organizzare() in dplyr

df <- structure(list(var1 = c(1L, 2L, 2L, 3L, 1L, 1L, 3L, 2L, 4L, 4L 
), var2 = structure(c(10L, 1L, 8L, 3L, 5L, 4L, 7L, 9L, 2L, 6L 
), .Label = c("b", "c", "f", "h", "i", "o", "s", "t", "w", "x" 
), class = "factor"), var3 = c(7L, 5L, 5L, 8L, 5L, 8L, 6L, 7L, 
    5L, 8L), var4 = structure(c(8L, 5L, 1L, 4L, 7L, 4L, 3L, 6L, 9L, 
    2L), .Label = c("b", "c", "d", "e", "f", "h", "i", "w", "y"), 
    class = "factor")), .Names = c("var1", "var2", "var3", "var4"), 
    row.names = c(NA, -10L), class = "data.frame") 

# this is the normal way to arrange df with dplyr 
df %>% arrange(var3, var4) 

# but none of these (below) work for passing a vector of variables 
vector_of_vars <- c("var3", "var4") 
df %>% arrange(vector_of_vars) 
df %>% arrange(get(vector_of_vars)) 
df %>% arrange(eval(parse(text = paste(vector_of_vars, collapse = ", ")))) 
+3

Imo, l'uso di%>% deve essere salvato per il concatenamento, come è piuttosto brutta ... (per le azioni singole <- oppure = funziona bene ... – Kevin

risposta

21

Hadley non ha reso questo ovvio nel file della guida - solo nella sua vignetta NSE. Le versioni delle funzioni seguite da underscore utilizzano la valutazione standard, in modo da passare loro i vettori di stringhe e simili.

Se ho capito bene il tuo problema, puoi semplicemente sostituire arrange() con arrange_() e funzionerà.

==== === modificare

passare il vettore di corda come argomento .dots quando lo fai.

> df %>% arrange_(.dots=c("var1","var3")) 
    var1 var2 var3 var4 
1  1 i 5 i 
2  1 x 7 w 
3  1 h 8 e 
4  2 b 5 f 
5  2 t 5 b 
6  2 w 7 h 
7  3 s 6 d 
8  3 f 8 e 
9  4 c 5 y 
10 4 o 8 c 
+2

Stavo pensando anche a questo, ma se fai 'df%>% arrange_ (vector_of_vars)', sembra ignorare il secondo elemento e ordina solo sul primo elemento. do 'df%>% arrange_ (vector_of_vars [1], vector_of_vars [2])', quindi ordina su entrambi i valori.Presco che ci sia un approccio più elegante rispetto al secondo metodo, ma non sono sicuro di cosa sia – eipi10

+0

'' 'arrangement _()' '' sembra ignorare la seconda colonna. @ eipi10 la tua soluzione funzionerebbe, ma il problema è che ci può essere un numero arbitrario di elementi s in '' 'vector_of_vars'''. – rsoren

+0

Non stavo dicendo che il mio secondo metodo era buono. Stavo solo cercando di limitare il problema di capire perché l'approccio apparentemente "naturale" non funziona e fornire anche una soluzione temporanea, se non elegante. Spero che @Hadley salti dentro e ci edifichi. – eipi10

3

Prova questo:

df %>% do(do.call(arrange_, . %>% list(.dots = vector_of_vars))) 

e in realtà questo può essere scritto più semplicemente come:

df %>% arrange_(.dots = vector_of_vars) 

anche se a questo punto credo che la sua lo stesso di una soluzione implicita di farnsy.

+0

Questo non ha funzionato per me, vedere [il mio post] (http://stackoverflow.com/questions/38052325). – zx8754

4

Nella nuova versione (di prossima uscita 0.6.0 di dplyr) possiamo fare uso della quosures

library(dplyr) 
vector_of_vars <- quos(var1, var3) 
df %>% 
    arrange(!!! vector_of_vars) 
# var1 var2 var3 var4 
#1  1 i 5 i 
#2  1 x 7 w 
#3  1 h 8 e 
#4  2 b 5 f 
#5  2 t 5 b 
#6  2 w 7 h 
#7  3 s 6 d 
#8  3 f 8 e 
#9  4 c 5 y 
#10 4 o 8 c 

Quando ci sono più di una variabile, usiamo quos e per una sola variabile Si tratta quo . Il quos restituirà un list di variabili quotate e all'interno arrange, abbiamo unquote il list utilizzando !!! per la valutazione

Problemi correlati