2

Apparently I am too stupid to enter the correct search terms, b/c I think that my question is not unique at all.

How to refer to a variable by string in the i part of data.table? with and ..x are all good for the j part, but what would be the equivalent in the i part? Do I have to use evil eval (pun intended ;)

library(data.table)
dt <- data.table(x = 1:4, y = 4:1)

my_filter_fun <- function(var = names(dt)) {
  var <- match.arg(var)
  dt[eval(parse(text = paste(var, "== 1")))]
}
my_filter_fun("x")
my_filter_fun("y")

What is the idiomatic way in data.table to do so? Coming from dplyr I think I am looking for the equivalent of quosures for data.table?

Bonus question: how could i implement my_filter_fun such that such a call

my_filter_fun(x > 1)

would return the same result as

dt[x > 1]
2
  • 1
    might be relevant: stackoverflow.com/questions/24833247/… and stackoverflow.com/… Commented May 25, 2020 at 22:49
  • Wow, a great read. Totally immersed into all the links from that post. It does answer a lot f my other questions too and also questions I did not even have yet :) +1 Commented May 26, 2020 at 9:00

2 Answers 2

3

For your first question, I suggest using get() to avoid the evil of eval():

my_filter_fun <- function(var = names(dt)) {
  var <- match.arg(var)
  dt[get(var) == 1]
}
my_filter_fun("x")
   x y
1: 1 4

For the bonus question, you could do the following. It can be simplified though - just that I don't know how.

bonus_filter_fun <- function(filter) {
  filter <- deparse(substitute(filter))
  dt[eval(parse(text = filter))]
}
bonus_filter_fun(x > 1)
   x y
1: 2 3
2: 3 2
3: 4 1
Sign up to request clarification or add additional context in comments.

2 Comments

Perfect! It is still a bit mind-boggling to me to use data.table efficiently in functions (being more of a dplyr guy myself - and there quasiquotation solves most of the probs)
see stackoverflow.com/a/57432125/1989480. Hence, maybe something like bonus_filter_fun <- function(iexpr) { eval(substitute(dt[cond], list(cond=substitute(iexpr)))) }
0

You have to use esoteric R magic, but not eval. What you are asking about is NSE or non-standard evaluation. Here's an example similar to yours:

theDf <- tibble(Sticks = 4:7, Stones = 9:12)
#' @title Create a new column by adding 8 to one of the existing columns.
a8Col <- function(df, newName, existName){
  existName <- enquo(existName)
  df %>%
    mutate(!! newName := !! existName + 8L )
}

R > a8Col(theDf, "Bones", Sticks)
# A tibble: 4 x 3
Sticks Stones Bones
<int>  <int> <int>
1      4      9    12
2      5     10    13
3      6     11    14
4      7     12    15
R > a8Col(theDf, "Bones", Stones)
# A tibble: 4 x 3
Sticks Stones Bones
<int>  <int> <int>
1      4      9    17
2      5     10    18
3      6     11    19
4      7     12    20

Notice that I didn't have to put quotes around Sticks or Stones in the calls to a8Col.

NSE is a hard topic. Hadley Wickham has written two chapter on it, (Quasiquotation and Evaluation) in his "Advanced R" book.

1 Comment

Thanks,. This is, however, dplyr syntax which I am very well aware of. What I am asking is to do the same in data.table though.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.