Search code examples
rdplyrrlangnse

How to perform NSE on the left hand side of a dplyr function?


Consider

library(dplyr)
assign_rhs <- function(df, rhs) {
  df %>%
    mutate(lhs = {{rhs}})
}

a = data.frame(b = 1, c = 2)

assign_rhs(a, b)

will yields:

  b c lhs
1 1 2   1

and I can do assign_rhs(a, c) as well to assign lhs to c instead of b.

How do I do it so that the lhs can also receive the NSE {{}} treatment provided by {rlang}?

I tried

library(dplyr)
assign_lhs_rhs <- function(df, lhs, rhs) {
  df %>%
    mutate({{lhs}} = {{rhs}})
}

a = data.frame(b = 1, c = 2)

assign_lhs_rhs(lhs, b)

but I get error when defining the function

Error: unexpected '=' in:
"  df %>%
    mutate({{lhs}} ="

Solution

  • If you use := instead of = you can use NSE on the left-hand side of the assignment:

    assign_lhs_rhs <- function(df, lhs, rhs) {
        df %>%
            mutate({{lhs}} := {{rhs}})
    }
    
    a = data.frame(b = 1, c = 2)
    
    assign_lhs_rhs(a, out, b)
    

    Output:

      b c out
    1 1 2   1
    

    I'm not an expert on non-standard evaluation, but as far as I know the reason for this is that it's not possible to override the way = works, so it has to be done via a new operator :=.