valutazione standard in dplyr: sumar_ sulla variabile data come stringa di caratteri

Voglio fare riferimento a un nome di colonna sconosciuto all’interno di un summarise . Le funzioni di valutazione standard introdotte in dplyr 0.3 consentono di fare riferimento ai nomi delle colonne utilizzando variabili, ma ciò non sembra funzionare quando si chiama una funzione di base R all’interno di un summarise ad esempio.

 library(dplyr) key <- "v3" val <- "v2" drp <- "v1" df <- data_frame(v1 = 1:5, v2 = 6:10, v3 = c(rep("A", 3), rep("B", 2))) 

La df ha questo aspetto:

 > df Source: local data frame [5 x 3] v1 v2 v3 1 1 6 A 2 2 7 A 3 3 8 A 4 4 9 B 5 5 10 B 

Voglio eliminare v1, raggruppare per v3 e sumre v2 per ogni gruppo:

 df %>% select(-matches(drp)) %>% group_by_(key) %>% summarise_(sum(val, na.rm = TRUE)) Error in sum(val, na.rm = TRUE) : invalid 'type' (character) of argument 

La versione NSE di select() funziona bene, poiché può corrispondere a una stringa di caratteri. La versione SE di group_by() funziona bene, poiché ora può accettare variabili come argomenti e valutarle. Tuttavia, non ho trovato un modo per ottenere risultati simili quando si utilizzano le funzioni di base R all’interno dplyr funzioni dplyr .

Cose che non funzionano:

 df %>% group_by_(key) %>% summarise_(sum(get(val), na.rm = TRUE)) Error in get(val) : object 'v2' not found df %>% group_by_(key) %>% summarise_(sum(eval(as.symbol(val)), na.rm = TRUE)) Error in eval(expr, envir, enclos) : object 'v2' not found 

Ho esaminato diverse domande correlate , ma nessuna delle soluzioni proposte ha funzionato per me finora.

Con il rilascio del pacchetto rlang e l’aggiornamento da 0.7.0 a dplyr, questo è ora abbastanza semplice.

Quando si desidera utilizzare una stringa di caratteri (ad esempio “v1”) come nome di variabile, è sufficiente:

  1. Converti la stringa in un simbolo usando sym() dal pacchetto rlang
  2. Nella tua chiamata di funzione, scrivi !! di fronte al simbolo

Ad esempio, dovresti fare quanto segue:

 my_var < - "Sepal.Length" my_sym <- sym(my_var) summarize(iris, Mean = mean(!!my_sym)) 

Più compatto, puoi combinare il passo della conversione della stringa in un simbolo con sym() e prefisso con !! quando scrivi la tua chiamata di funzione.

Ad esempio, potresti scrivere:

 my_var < - "Sepal.Length" summarize(iris, mean(!!sym(my_var))) 

Per tornare al tuo esempio originale, puoi fare quanto segue:

 library(rlang) key < - "v3" val <- "v2" drp <- "v1" df <- data_frame(v1 = 1:5, v2 = 6:10, v3 = c(rep("A", 3), rep("B", 2))) df %>% # NOTE: we don't have to do anything to `drp` # since the matches() function expects a character string select(-matches(drp)) %>% group_by(!!sym(key)) %>% summarise(sum(!!sym(val), na.rm = TRUE)) 

Dettagli aggiuntivi

Di tutta la documentazione ufficiale che spiega come utilizzare sym() e !! funziona, questi sembrano essere i più accessibili:

  1. dplyr vignette: programmazione con dplyr

  2. La sezione del libro di Hadley Wickham "Advanced R" su metaprogrammazione

Si noti che questa risposta non si applica a dplyr >= 0.7.0 , ma alle versioni precedenti.

[ dplyr 0.7.0 ] ha un nuovo approccio alla valutazione non standard (NSE) chiamata tidyeval. È descritto in dettaglio nella vignette("programming") .


La vignetta dplyr sulla valutazione non standard è utile qui. Controlla la sezione “Miscelazione di costanti e variabili” e scopri che è ansible utilizzare la funzione interp dal pacchetto lazyeval e “[u] as.name se hai una stringa di caratteri che fornisce un nome di variabile”:

 library(lazyeval) df %>% select(-matches(drp)) %>% group_by_(key) %>% summarise_(sum_val = interp(~sum(var, na.rm = TRUE), var = as.name(val))) # v3 sum_val # 1 A 21 # 2 B 19 

Passa l’argomento .dots un elenco di stringhe che costruiscono le stringhe usando paste , sprintf o usando l’interpolazione delle stringhe dal pacchetto gsubfn tramite fn$list al posto di list come facciamo qui:

 library(gsubfn) df %>% group_by_(key) %>% summarise_(.dots = fn$list(mean = "mean($val)", sd = "sd($val)")) 

dando:

 Source: local data frame [2 x 3] v3 mean sd 1 A 7.0 1.0000000 2 B 9.5 0.7071068 

Nuovo aggiornamento dplyr:

La nuova funzionalità di dplyr può aiutare con questo. Invece di stringhe per le variabili che richiedono una valutazione non standard, usiamo le quosures quo() . Annulliamo il quoting con un’altra funzione !! . Per ulteriori informazioni su questi vedi questa vignetta . Avrai bisogno della versione dello sviluppatore di dplyr fino alla versione completa.

 library(dplyr) #0.5.0.9004+ key < - quo(v3) val <- quo(v2) drp <- "v1" df <- data_frame(v1 = 1:5, v2 = 6:10, v3 = c(rep("A", 3), rep("B", 2))) df %>% select(-matches("v1")) %>% group_by(!!key) %>% summarise(sum(!!val, na.rm = TRUE)) # # A tibble: 2 × 2 # v3 `sum(v2, na.rm = TRUE)` #   # 1 A 21 # 2 B 19