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)
}