我有一个子集函数,它接受用户定义类的对象,传递给函数的条件,并将该条件作为对象的属性添加。
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
}
我可以将此功能称为:
sdf <- subset.survey.data.frame(sdf,dsex =="Male")
这会在user_conditions属性中添加dsex ==“Male”。
但是,如果我想从另一个函数和循环中调用它,它会传递v1和v2,而不是实际的变量名。
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)
如何修改子集函数以便我可以获取v1和v2的名称,然后将条件添加到对象中?
这是SDF,lvls和rhs_vars的样子
sdf <- list(user_conditions = list(),default_conditions = list(default_conditions) ,data = data_Laf, weights=weights, pvvars=pvs, fileDescription = f)
这里,data_Laf是一个LaF对象(http://cran.r-project.org/web/packages/LaF/index.html),权重,pvs和f都是列表。
rhs_vars <- rhs.vars(y ~ dsex + b017451) # from formula.tools package
> rhs_vars
[1] "dsex" "b017451"
lvls是数据框中列的级别
lvls <- levels(data[,rhs_vars[1]])
"Male" "Female"
这是一个有效的例子:
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
}
答案 0 :(得分:1)
正如@nrussell暗示的那样,substitute
应该可以帮助你构建表达式。然后你只需要评估它们。这是一个简单的例子
v1 <- quote(cyl)
v2 <- 6
eval(substitute(subset(mtcars, v1==v2), list(v1=v1, v2=v2)))
如果您的v1
是一个字符类,您可以将其转换为符号vi as.name()
,因为您需要符号而不是字符才能使表达式起作用。
v1 <- "cyl"
v2 <- 6
eval(substitute(subset(mtcars, v1==v2), list(v1=as.name(v1), v2=v2)))
答案 1 :(得分:1)
如果您正在控制“inside”参数,那么它就不那么简单了:
if(inside) condition_call = call(substitute(condition[[1]]), as.name(condition[[2]]), condition[[3]])
这当然假设人们只使用二元条件,但你可以扩展上述逻辑。