Calling/passing variables from a function to function

71 Views Asked by At

I'm trying to call some variable names using rlang and tidyselect from f1() to f2(). But it doesn't print.

library(rlang)
library(dplyr)
library(R.utils)
library(tidyselect)

db <- tibble(
  D = as.factor(rbinom(10, size=1, p=0.7)),
  X1 = 10*rnorm(10),
  CRT1 = 15*rnorm(10),
  CRT2 = 12*rnorm(10))


f1 <- function(data, varname){
  #Can I use in this function `tidyselect` syntax Like f2()? 
  
  varname = enquo(varname)
  sdf <- data %>%
    group_by(D) %>%  ### ---- D variable called in f2()
    summarise(a = mean(!!varname), 
              b = sd(!!varname), .groups = "drop")

  list(evl = (sum(sdf$b) > 0), df = data)
}

f2 <- function(data, controls){
  
  controls = enexpr(controls)
  cols <- tidyselect::eval_select(controls, data)
  col_nms <- names(cols)
  
  res = f1(data, X1) ### ---- X1 variable called in f2()
  if (res$evl) {
    data = res$df
    printf("The variable calculated is %s
and the variable grouped %s \n\n", names(data$X1), names(data$D))
  }
  
  for (i in col_nms) {
    printf("The control variable is %s,grouped by %s, and calulated by %s \n", i, names(data$D), names(data$X1))
  }
  
  
}


f2(db, controls = c("CRT1", "CRT2"))
#> 

Other question: Can I use in f1 function tidyselect syntax like f2()?

Edit

I need print variable names/values using the output from f1().

f2 <- function(data, controls){
  
  controls = enexpr(controls)
  cols <- tidyselect::eval_select(controls, data)
  col_nms <- names(cols)
  
  res = f1(data, X1) ### ---- X1 variable called on f2()
  if (res$evl) {
    data = res$df
    printf("The variable calculated is %s
and the variable grouped %s \n\n", names(data$X1), names(data$D))
  }
  
  for (i in col_nms) {
    printf("The control variable is %s,grouped by %s, and calulated by %s.
The first value of %s is %f \n", 
           i, names(data$D), names(data$X1), names(data$D), data[1,2])
  }
  
}

What I need (output)

#The variable calculated is X1
#and the variable grouped D
#
#The control variable is CRT1, grouped by D and calulated by X1. The first value of D is 21.6.
#The control variable is CRT2 grouped by D and calulated by X1 The first value of D is 21.6
1

There are 1 best solutions below

3
Juan C On BEST ANSWER

Since both X1 and D are hardcoded into your function, there's no reason to do something more elaborate than using those strings. I changed a couple things here and there too:

f1 <- function(data, varname){
  #Can I use in this function `tidyselect` syntax Like f2()? 
  

  sdf <- data %>%
    group_by(D) %>%  ### ---- D variable called in f2()
    summarise(a = mean({{varname}}), 
              b = sd({{varname}}), .groups = "drop")
  
  list(evl = (sum(sdf$b) > 0), df = data)
}

f2 <- function(data, controls){
  
  
  cols <- data %>% select({{controls}})
  col_nms <- names(cols)
  print(col_nms)
  
  res = f1(data, X1) ### ---- X1 variable called in f2()

  if (res$evl) {
    data = res$df
    data
    printf("The variable calculated is %s
and the variable grouped %s \n\n", 'X1', 'D')
  }
  
  for (i in col_nms) {
    printf("The control variable is %s,grouped by %s, and calulated by %s \n", i, 'D', 'X1')
  }
  
  
}

If you need something more abstract, please edit your example accordingly

Output:

The variable calculated is X1
and the variable grouped D 

The control variable is CRT1,grouped by D, and calulated by X1 
The control variable is CRT2,grouped by D, and calulated by X1