1

I'm creating a function for my co-workers to easily analyze some pre-specified datasets. I would like for them to be able to pass "i" arguments to select rows. To make it more robust, I would like to be able pass this argument with or without quotes.

Here is an example that works with quotes …

x <- data.table(x = c(1,1,1,2,2,2,3,3,3), 
  sex = c("M", "M", "F","M", "F","M", "F","M", "F"))
test.function <- function(my.dt, ...){
  where <- parse(text = paste0(list(...))) 
  my.dt <- my.dt[eval(where), ]
  return(my.dt)
}
tmp <- test.function(x, 'x==3 | sex=="F"')
head(tmp) 

If I remove the quotes, it fails saying "object 'sex' not found"…

x <- data.table(x = c(1,1,1,2,2,2,3,3,3), 
  sex = c("M", "M", "F","M", "F","M", "F","M", "F"))
test.function <- function(my.dt, ...){
  where <- parse(text = paste0(list(...))) 
  my.dt <- my.dt[eval(where), ]
  return(my.dt)
}
tmp <- test.function(x, x==3 | sex=="F")
head(tmp)

In addition to the above, I have many failed attempts using quote, substitution and rlang: like this failed example …

x <- data.table(x = c(1,1,1,2,2,2,3,3,3), 
                sex = c("M", "M", "F","M", "F","M", "F","M", "F"))
test.function <- function(my.dt, ...){
  where <- rlang::quos(...)
  my.dt <- my.dt[!!where, ]
  return(my.dt)
}
tmp <- test.function(x, 'x==3 | sex=="F"')
head(tmp, 10)

In addition to any ideas for solutions, I would be grateful if someone could point me toward an simpleton's online resource for understanding symbols/expressions/quotes/etc. As I dug into this problem I realized that I have some serious gaps in my understanding of how R works.

BTW, I've already read through the following, but neither was able to help me: Passing function argument to data.table i and Passing multiple arguments to data.table inside a function .

4
  • How about passing x, sex, and the operator as separate arguments? test.function(x, 3, "F", "|"). Then set up your function to handle each input as a separate variable? Commented Nov 8, 2019 at 19:59
  • Thanks for your comment Chris. I'm trying to keep this as simple as possible for the end user, who will not be a proficient R user. That's why I want I want them to be able to pass the argument with or without quotes. Thanks again. Commented Nov 8, 2019 at 20:26
  • If you remove quotes you should not use parse anymore. Parse expects character, not an expression. Commented Nov 9, 2019 at 3:33
  • Thank you @jangorecki. After seeing Matt's solution, that became clear to me. Commented Nov 12, 2019 at 22:02

1 Answer 1

1

There may be other (better) options, but you can wrap it in tryCatch and use bquote for the unquoted argument

test.function <- function(my.dt, ...){
    where <- tryCatch(parse(text = paste0(list(...))),  error = function (e) parse(text = paste0(list(bquote(...)))))
    my.dt <- my.dt[eval(where), ]
    return(my.dt)
  }

tmp <- test.function(x, 'x==3 | sex=="F"')
head(tmp) 
   x sex
1: 1   F
2: 2   F
3: 3   F
4: 3   M
5: 3   F

tmp <- test.function(x, x==3 | sex=='F')
head(tmp)
   x sex
1: 1   F
2: 2   F
3: 3   F
4: 3   M
5: 3   F
Sign up to request clarification or add additional context in comments.

Comments

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.