2

I have the following piece of code that merges two dataframes:

prim <- data.frame("t"=2007:2012,
                   "a"=1:6,
                   "b"=7:12)

secnd <- data.frame("t"=2012:2013,
                    "a"=c(5, 7))

final_df <- prim %>% full_join(secnd, by = 't') %>%
  mutate(a = coalesce(as.integer(a.y),a.x)) %>%
  select(t,a,b)

Is it possible to use a variable name instead of hard-coding a as done above? I.e., is it possible to make the following non-functioning code work?

var <- "a"
final_df <- prim %>% full_join(secnd, by = 't') %>%
  mutate(var = coalesce(as.integer(var.y),var.x)) %>%
  select(t,var,b)
N08
  • 1,265
  • 13
  • 23

2 Answers2

2

One option would be to convert to symbol with syms and evaluate (!!!)

library(tidyverse)
var <- "a"
prim %>% 
  full_join(secnd, by = "t") %>%
  mutate_at(vars(starts_with(var)), as.integer) %>% 
  transmute(t, !! var := coalesce(!!! rlang::syms(paste0(var, c(".y", ".x")))), b)
#     t a  b
#1 2007 1  7
#2 2008 2  8
#3 2009 3  9
#4 2010 4 10
#5 2011 5 11
#6 2012 5 12
#7 2013 7 NA
akrun
  • 874,273
  • 37
  • 540
  • 662
  • Thanks. The output is not quite the same though as when I run the code in my own example in the OP? – N08 Nov 02 '18 at 15:50
  • 1
    @N08 I got it why you got a different result. The columns are reversed – akrun Nov 02 '18 at 15:54
  • Thanks - which columns do you mean? – N08 Nov 02 '18 at 15:57
  • 1
    @N08 I meant instead of `.x, .y`, you had it `.y`, .`x` – akrun Nov 02 '18 at 15:57
  • It is supposed so be `y` first, then `x` (so the OP is correct). But if I make the change in your solution, then I get something different than in the OP – N08 Nov 02 '18 at 16:00
  • Also, one more thing is that one of the column is of type different from the other, so have to change it before doing the `coalecse` – akrun Nov 02 '18 at 16:01
  • Sorry, you lost me. Would it be possible to update your answer so the output is the same as in my OP? Thanks, I would really appreciate it – N08 Nov 02 '18 at 16:04
  • 1
    The issue with the earlier part was that I used a.x, a.y in that order. So, whenever there is a case where the rows have two non-NA, the first value is selected. – akrun Nov 02 '18 at 16:06
  • Is it possible to pass a vector of variables to `transmute` in the last line? E.g., pass a vector `vars <- c("t", "b")` instead of writing it manually – N08 Nov 02 '18 at 16:23
  • 1
    @N08 Yes you can do it. But convert to symbol with `syms` and do `!!!` – akrun Nov 02 '18 at 16:25
  • 1
    i.e. `%>% transmute(!!! rlang::syms(vars), !! var := coalesce(!!! rlang::syms(paste0(var, c(".y", ".x")))))` – akrun Nov 02 '18 at 16:56
1

We can use the := assignment operator to allow standard-evaluation on the left hand side:

library(dplyr)
library(rlang)

var <- "a"
final_df <- prim %>% full_join(secnd, by = 't') %>%
  mutate(!!var := coalesce(as.integer(!!sym(paste0(var, ".y"))),!!sym(paste0(var, ".x")))) %>%
  select(t,var,b)
acylam
  • 18,231
  • 5
  • 36
  • 45
  • I get the error `Error in sym(paste0(var, ".y")) : could not find function "sym"` when I run the code – N08 Nov 02 '18 at 15:55