rdplyrnser-glue

Dynamic name with glue in mutate call


I want to create a function that takes up as the first argument the name of a data set, and as a second argument, part of a column's name from the dataframe. I then want to use glue to dynamically construct the column name, in the function, and use that column in a mutate call, like so:

library(tidyverse)

tmp <- 
  function(data, type){
  var <- glue::glue("Sepal.{type}")
  iris |> 
    select({{var}}) |> 
    mutate("{var}" := mean({{var}}))
}

I've tried a lot of things, but I struggle to find a solution where the column is called both for the name of the new column (here, "{var}") and for the computation of the new column (here, mean({{var}})). What should one do in such cases?

Here, calling tmp(iris, "Length") should return a 150x1 data.frame with the mean value in all rows.

tidyverse solution are preferred, or any pipe-based answers.


Solution

  • You can use mean({{var}}) if you modify your code just a little bit, for example, using as.symbol (or as.name) to define var, instead of a glue char

    tmp <- function(data, type) {
        var <- as.symbol(glue::glue("Sepal.{type}"))
        data |>
            select(var) |>
            mutate("{var}" := mean({{ var }}))
    }
    

    For some alternatives, I guess you can try get(var) or !!rlang::syms(var), for example

    tmp <- function(data, type) {
        var <- glue::glue("Sepal.{type}")
        data |>
            select({{ var }}) |>
            mutate("{var}" := mean(get(var)))
    }
    

    or

    tmp <- function(data, type) {
        var <- rlang::sym(glue::glue("Sepal.{type}"))
        data |>
            select(var) |>
            mutate("{var}" := mean(!!var))
    }