1

I have a subset function that takes in an object of a user defined class, a condition passed to the function, and adds that condition as an attribute of the object.

subset.survey.data.frame <- function(x, condition, drop=FALSE, inside=FALSE) {
  if(inside) {
    condition_call <- deparse(substitute(condition, env=parent.frame(n=1)))
  } 
  else {
    condition_call <- substitute(condition)
  }

  x[["user_conditions"]] <- unique(c(x[["user_conditions"]],list(condition_call)))
  cat("Subset Conditions have been added to SDF")
  x
}

I can call this function as:

sdf <- subset.survey.data.frame(sdf,dsex =="Male")

This adds dsex == "Male" in user_conditions attribute.

However, if I want to call it from within another function and a loop, it passed v1 and v2, instead of the actual variable names.

 for(i in 1:length(lvls)) {
    v1 <- rhs_vars[1]
    v2 <- lvls[i]
    print(v1) #"dsex"
    print(v2) #"Male"
    dsdf <- subset.survey.data.frame(sdf,  v1 == v2, inside=T)

How can I modify the subset function so that I can get the names of v1 and v2 and then add the condition to the object?

Here is what SDF, lvls, and rhs_vars looks like

sdf <- list(user_conditions = list(),default_conditions = list(default_conditions) ,data =    data_Laf, weights=weights, pvvars=pvs, fileDescription = f)

Here, data_Laf is an LaF object (http://cran.r-project.org/web/packages/LaF/index.html), weights, pvs, and f are all lists.

rhs_vars <- rhs.vars(y ~ dsex + b017451) # from formula.tools package
> rhs_vars
[1] "dsex"    "b017451"

lvls is the levels of a column in a dataframe

lvls <- levels(data[,rhs_vars[1]])
"Male" "Female"

Here is a working example:

 default_conditions= quote(rptsamp=="Reporting sample")
 sdf <- list(user_conditions = list(),default_conditions = list(default_conditions))
 class(sdf) <- "Userdefined"

subset.survey.data.frame <- function(x, condition, drop=FALSE, inside=FALSE) {
  if(inside) {
    condition_call <- deparse(substitute(condition, env=parent.frame(n=1)))
  } 
  else {
    condition_call <- substitute(condition)
  }

  x[["user_conditions"]] <- unique(c(x[["user_conditions"]],list(condition_call)))
  cat("Subset Conditions have been added to X")
  x
}
sdf <- subset.survey.data.frame(sdf,dsex =="Male")
print(sdf)
#This gives the correct answer and adds dsex == "Male" to user conditions


#Creating some sample data
dsex =c('1','2','1','1','2','1','1','2','1')
b017451 <- sample(c(1:100), 9)
y <- rep(10, 9)
data <- data.frame(dsex, y, b017451)
data[,'dsex'] <- factor(data[,'dsex'], levels=c("1", "2"), labels=c('Male','Female'))
require(formula.tools)
rhs_vars <- rhs.vars(y ~ dsex + b017451)
lvls <- levels(data[,rhs_vars[1]])

for(i in 1:length(lvls)) {
    v1 <- rhs_vars[1]
    v2 <- lvls[i]
    print(v1) #"dsex"
    print(v2) #"Male"
    dsdf <- subset.survey.data.frame(sdf,  v1 == v2, inside=F)
    print(dsdf)
#this doesnt give the correct answer and adds v1 == v2 to user conditions

    break
}
6
  • 1
    If I understand your question correctly, substitute should get you what you are looking for. Commented Jan 13, 2015 at 19:24
  • substitute results in v1 == v2 Commented Jan 13, 2015 at 20:02
  • Would you mind adding your other objects (sdf, lvls, rhs_vars)? Commented Jan 13, 2015 at 20:11
  • Edited the description to include SDF, lvls, and rhs_vars Commented Jan 13, 2015 at 20:25
  • 1
    How about default_conditions --> Error: object 'default_conditions' not found ? Try starting a clean session and run only the code included in your question to make sure that you add all of the necessary objects to make this problem reproducible. Commented Jan 13, 2015 at 20:39

2 Answers 2

1

As @nrussell was alluding to, substitute should help you build your expressions. Then you just need to evalute them. Here's a simple example

v1 <- quote(cyl)
v2 <- 6
eval(substitute(subset(mtcars, v1==v2), list(v1=v1, v2=v2)))

If your v1 is a character class, you can convert it to a symbol vi as.name() because you need a symbol and not a character for the expression to work.

v1 <- "cyl"
v2 <- 6
eval(substitute(subset(mtcars, v1==v2), list(v1=as.name(v1), v2=v2)))
Sign up to request clarification or add additional context in comments.

Comments

1

If you're controlling the "inside" parameter, then isn't it as simple as:

if(inside) condition_call = call(substitute(condition[[1]]), as.name(condition[[2]]), condition[[3]])

This of course assumes people are only using binary conditions, but you can extend the above logic.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.