8

I would like to have a function which calls subset, and passes on a subset argument:

df <- data.frame(abc=c("A","A","B","B"),value=1:4)
subset(df,abc=="A")
## works of course:
#  abc value
#1   A     1
#2   A     2

mysubset <- function(df,ssubset)
  subset(df,ssubset)

mysubset(df,abc=="A")
## Throws an error
# Error in eval(expr, envir, enclos) : object 'abc' not found

mysubset2 <- function(df,ssubset)
  subset(df,eval(ssubset))

mysubset2(df,expression(abc=="A"))
## Works, but needs expression

I tried with substitute, but was not able to find the right combination. How can I get this working?

Florian Bw
  • 746
  • 1
  • 7
  • 16

2 Answers2

14

You need eval() and parse() in there too:

mysubset <- function(df, ssubset) {
  subset(df, eval(parse(text=ssubset)))
}
mysubset(df, "abc=='A'")
#   abc value
# 1   A     1
# 2   A     2

Note that you need to nest quotes, so switch back and forth between " and ' as necessary.


Based on your comment, perhaps something like this is also of interest:

mysubset <- function(df, ...) {
  ssubset <- deparse(substitute(...))
  subset(df, eval(parse(text = ssubset)))
}

USAGE: mysubset(df, abc=='A')

A5C1D2H2I1M1N2O1R2T1
  • 190,393
  • 28
  • 405
  • 485
  • Thanks for the answer. Do you know if there is a possibility to do it without quotes? – Florian Bw Dec 19 '13 at 13:27
  • Something like this you mean? `mysubset <- function(df, ...) { ssubset <- deparse(substitute(...)); subset(df, eval(parse(text = ssubset))) }`. USAGE: `mysubset(df, abc=='A')` – A5C1D2H2I1M1N2O1R2T1 Dec 19 '13 at 16:13
  • Great, thank you, accepting your answer. Would be nice if you can add this possibility also in your main answer. – Florian Bw Dec 20 '13 at 14:37
5

The A5C1D2H2I1M1N2O1R2T1 answer works, but you can skip the whole deparse/parse cycle by simply using:

mysubset <- function(df, p) {
  ps <- substitute(p)
  subset(df, eval(ps))
}
fikovnik
  • 3,473
  • 3
  • 28
  • 29