Considere un tibble donde cada columna es un vector de caracteres que puede tomar muchos valores, digamos "A" a "F".
library(tidyverse)
sample_df <- tibble(q1 = c("A", "B", "C"), q2 = c("B", "B", "A"))
Deseo crear una función que tome el nombre de una columna como argumento, y recodifique esa columna para que cualquier respuesta "A" se convierta en un NA y el df se devuelva como está. La razón para diseñarlo de esta manera es encajar en una tubería más amplia que realiza una serie de operaciones utilizando una columna dada.
Hay muchas maneras de hacer esto. Pero estoy interesado en comprender cuál sería el mejor enfoque idiomático tidy_eval / tidyverse. Primero, el nombre de la pregunta debe estar en el lado izquierdo de un verbo mutado, por lo que usamos los operadores !!
y :=
adecuadamente. Pero entonces, ¿qué poner en el lado derecho?
fix_question <- function(df, question) {
df %>% mutate(!!question := recode(... something goes here...))
}
fix_question(sample_df, "q1") # should produce a tibble whose first column is (NA, "B", "C")
Mi pensamiento inicial fue que esto funcionaría:
df %>% mutate(!!question := recode(!!question, "A" = NA_character_))
Pero, por supuesto, el bang-bang dentro de la función solo devuelve la cadena de caracteres literal (por ejemplo, "q1"). Terminé tomando lo que parece una ruta hacky para hacer referencia a los datos en el lado derecho, usando el [[
operador base R y confiando en la .
construcción de dplyr, y funciona, por lo que en cierto sentido he resuelto mi problema subyacente:
df %>% mutate(!!question := recode(.[[question]], "A" = NA_character_))
Estoy interesado en recibir comentarios de personas que son muy buenas en tidyeval en cuanto a si hay una forma más idiomática de hacer esto, con la esperanza de que ver un ejemplo trabajado mejoraría mi comprensión del conjunto de funciones tidyeval en general. ¿Alguna idea?
q1
(símbolo) y"q1"
(cadena):df %>% mutate_at( vars(!!ensym(question)), recode, A = NA_character_)
Respuestas:
Aquí, en el lado derecho de
:=
, podemos especificarsym
convertir a símbolo y luego evaluar (!!
)Un mejor enfoque que funcionaría para las entradas citadas y no citadas es
ensym
fuente
Puede usar el método "rizado rizado" ahora si tiene argot> = 0.4.0 .
Explicación gracias a @ eipi10:
Esto combina el proceso de dos pasos de citar y luego citar en un solo paso, por lo que
{{question}}
es equivalente a!!enquo(question)
Tenga en cuenta que, a diferencia del
ensym
enfoque, esto no funciona con los nombres de los personajes. Peor aún, hace lo incorrecto en lugar de simplemente dar un error.fuente
question
primero debe convertirse en un quosure (question = enquo(question)
) antes de usarse en la tubería dplyr.{{question}}
es equivalente a!!enquo(question)
.Puede hacer que la función sea un poco más flexible permitiendo que también se ingrese un vector de valores recodificados como argumento. Por ejemplo:
Tenga en cuenta que
recode.vec
está "entre comillas"!!!
. Puede ver lo que está haciendo con este ejemplo, adaptado de la viñeta Programación con dplyr (busque "empalme" para ver los ejemplos relevantes). Observe cómo!!!
"empalma" los pares de valores de recodificación en larecode
función para que se utilicen como...
argumento enrecode
.Si desea ejecutar potencialmente la función de recodificación en varias columnas, puede convertirla en una función que solo tome el nombre de una columna y un vector de recodificación. Parece que este enfoque sería más amigable con las tuberías.
O para recodificar una sola columna:
fuente