Home > database >  Create a frunction (data.table structure) with double curly braces {{ using rlang
Create a frunction (data.table structure) with double curly braces {{ using rlang

Time:10-06

Is it possible to do a function using the rlang structure with data.table.

For example:

Without data.table

library(data.table)
library(dplyr)

iris[1,1:2] = NA
iris[3,3:4] = NA

test_dt <- function(dt, col1) {
  
  #dt = data.table(iris)
  dt = dt %>% 
    na.omit(cols = c("Species",{{col1}}))
  
  return(dt)
}


I'm filtering rows with na.omit with data.table because is faster.

library(data.table)
library(dplyr)

data("iris")
iris[1,1:2] = NA
iris[3,3:4] = NA
dt = as_tibble(iris)

test_tibble <- function(dt, col1) {
  
  #dt = data.table(iris)
  dt = as_tibble(iris)
  dt = dt %>% 
    na.omit(cols = c({{col1}}))
  
  return(dt)
  
}

test_tibble(dt, Sepal.Length) #### It works
test_tibble(dt, "Sepal.Length") #### both works

Using data.table

test_dt <- function(dt, col1) {
  
  dt = data.table(iris)
  #dt = as_tibble(iris)
  dt = dt %>% 
    na.omit(cols = c({{col1}}))
  
  return(dt)
  
}

test_dt(dt, "Sepal.Length") ### It works
test_dt(dt, Sepal.Length)  ### Doesn't work

I would like to use the function test_dt() without "". It's possible?

Edit

tb2_2 = structure(list(X = c(0.512025410572104, 1.34199356465929, -1.25270649900694, 
                     -0.733000712714794, 0.45465371837226, -0.127917924970955, 0.31527125548264, 
                     NA, 1.48657524744542, -0.19959359633143), 
                     Y = c(-0.661273939978519, -12.7527853536461, -1.17638144073283, NA, 8.47888404561908, 
                           8.57745418700866, 9.31590763962404, NA, 4.25920544787551, 16.1806108716548), 
                     G = c(1, NA, 1, 1, 0, 1, 0, NA, 1, 1), 
                     U = c(-0.333914863990124, -1.12935646288322, -1.69358562462423, -0.395929701341583, 
                           0.539754714374008, -1.04544664173391, 1.22480232242127, NA, 0.444278569991649, 
                           0.0596820740502588), 
                     T = c(2000, 2001, 2002, 2003, 2004, 2005, 2006, NA, 2008, 2009), 
                     D = c(5.53807382142459, -4.45890044023787, -4.02776194571743, -2.40946010272286, 
                           0.517463695461427, NA, 1.44204693390199, NA, -8.22747683712939, -2.98560166016223), 
                     D0 = c(NA, -11.1320556669676, -3.56453610182438, 4.01976245984647, -5.99808700582389, 
                            9.96620396574901, 5.80036617369695, NA, 12.7934259732021, -9.79730042991476), 
                     CRT1 = c(-9.33852764928105, 29.1198381594211, 0.965478696195844, -23.8140405650042, 
                              -11.9346599938887, -7.18523176736665, 5.4838459604535, NA, -17.3985872962915, NA), 
               CRT2 = c(`1` = 2.93893603185069, `2` = 1.228446714169, `3` = 6.57588892581666, `4` = 5.50482229342548, 
                        `5` = 3.05717390177606, `6` = 4.25780138105421, `7` = 3.34442855446459, `8` = NA, 
                        `9` = NA, `10` = 4.40551845862642), 
               TREAT1 = c(`1` = -3.60020997182921, `2` = -13.9812320678151, `3` = -7.75227036654949, `4` = -6.01945591669384, 
                          `5` = 5.42171014384302, `6` = 4.31965280595445, `7` = 5.97147908515944, `8` = NA, 
                          `9` = 3.3287285084747, `10` = 11.7750924130284), 
               TREAT2 = c(`1` = -36.0020997182921, `2` = -139.812320678151, `3` = -77.5227036654949, `4` = -60.1945591669384, 
                          `5` = 54.2171014384302, `6` = 43.1965280595445, `7` = 59.7147908515944, `8` = NA, 
                          `9` = 33.287285084747, `10` = 117.750924130284), 
               rand_wei = c(-17.1969296658761, 22.9057780481208, -33.4966252613491, 57.3810802699894, 4.33294142856405, 
                            -12.579733621978, 20.3965087501415, NA, 57.0577414340694, 
                            39.6584493366088)), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -10L))


f <- function(data, type, arg1, arg2){
  
  data = data.table(data)
  
  arg1= rlang::as_string(rlang::ensym(arg1))
  arg2= rlang::as_string(rlang::ensym(arg2))
  
  if (cmd_type != "a") {
    
    data <- data %>% 
      na.omit(cols = c("Y", "G", "T", "D", {{arg1}}, {{arg2}}))
    
  } else{
    
    data = data %>% 
      na.omit(cols = c("Y",      "T", "D", "D0", {{arg1}}))
    
  }
  data
}

f(tb2_2, type= "a", arg1 = c(CRT1, CRT2), arg2 = TREAT1) #without data.table

CodePudding user response:

Since you would like to use the function test_dt() without "". Here is another solution (but it's not based on rlang or {{).

test_dt = function(dt, ...) {

  vars = lapply(as.list(substitute(list(...))[-1L]), 
                \(x) if(is.call(x)) as.list(x)[-1L] else x)
  
  if(!is.data.table(dt)) dt = as.data.table(dt)
  
  na.omit(dt, cols=as.character(unlist(vars)))
}

# testing
test_dt(iris, "Sepal.Length")                            # works
test_dt(iris, Sepal.Length)                              # works
test_dt(iris, Sepal.Length, Species, "Sepal.Width")      # works
test_dt(iris, c(Sepal.Length, Species), "Sepal.Width")   # works

CodePudding user response:

We could try

test_dt <- function(dt, col1) {
 col1 = rlang::as_string(rlang::ensym(col1))
  
  dt = data.table(iris)
  #dt = as_tibble(iris)
  dt = dt %>% 
    na.omit(cols = c(col1))
  
  return(dt)
  
}

-testing

> test_dt(dt, Sepal.Length)  ### Doesn't work
     Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
            <num>       <num>        <num>       <num>    <fctr>
  1:          5.1         3.5          1.4         0.2    setosa
  2:          4.9         3.0          1.4         0.2    setosa
  3:          4.7         3.2          1.3         0.2    setosa
  4:          4.6         3.1          1.5         0.2    setosa
  5:          5.0         3.6          1.4         0.2    setosa
 ---                                                            
146:          6.7         3.0          5.2         2.3 virginica
147:          6.3         2.5          5.0         1.9 virginica
148:          6.5         3.0          5.2         2.0 virginica
149:          6.2         3.4          5.4         2.3 virginica
150:          5.9         3.0          5.1         1.8 virginica
> 
> test_dt(dt, "Sepal.Length")
     Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
            <num>       <num>        <num>       <num>    <fctr>
  1:          5.1         3.5          1.4         0.2    setosa
  2:          4.9         3.0          1.4         0.2    setosa
  3:          4.7         3.2          1.3         0.2    setosa
  4:          4.6         3.1          1.5         0.2    setosa
  5:          5.0         3.6          1.4         0.2    setosa
 ---                                                            
146:          6.7         3.0          5.2         2.3 virginica
147:          6.3         2.5          5.0         1.9 virginica
148:          6.5         3.0          5.2         2.0 virginica
149:          6.2         3.4          5.4         2.3 virginica
150:          5.9         3.0          5.1         1.8 virginica

For the second case

 f <- function(data, cmd_type, arg1, arg2){
  
    data = data.table(data)
    
    controls <- map_chr(rlang::enexpr(arg1), ~ rlang::as_string(.x))[-1]
    treatments = rlang::as_string(rlang::ensym(arg2))

    if (cmd_type != "a") {
  
      data <- data %>% 
        na.omit(cols = c("Y", "G", "T", "D", controls, treatments))
  
    } else{
  
      data = data %>% 
        na.omit(cols = c("Y",      "T", "D", "D0", controls))
  
    }
    return(data)
  }
  • Related