如何在公式中按字符串使用引用变量?

Eri*_*een 40 string r names formula paste

在下面的最小示例中,我尝试vars在回归公式中使用字符串的值.但是,我只能将变量名称字符串("v2 + v3 + v4")传递给公式,而不是该字符串的实际含义(例如,"v2"是dat $ v2).

我知道有更好的方法来运行回归(例如lm(v1 ~ v2 + v3 + v4, data=dat)).我的情况更复杂,我想弄清楚如何在公式中使用字符串.有什么想法吗?

更新以下代码

# minimal example 
# create data frame
v1 <- rnorm(10)
v2 <- sample(c(0,1), 10, replace=TRUE)
v3 <- rnorm(10)
v4 <- rnorm(10)
dat <- cbind(v1, v2, v3, v4)
dat <- as.data.frame(dat)

# create objects of column names
c.2 <- colnames(dat)[2]
c.3 <- colnames(dat)[3]
c.4 <- colnames(dat)[4]

# shortcut to get to the type of object my full code produces
vars <- paste(c.2, c.3, c.4, sep="+")

### TRYING TO SOLVE FROM THIS POINT:
print(vars)
# [1] "v2+v3+v4"

# use vars in regression
regression <- paste0("v1", " ~ ", vars)
m1 <- lm(as.formula(regression), data=dat)
Run Code Online (Sandbox Code Playgroud)

更新:@Arun v1对于第一个示例中缺少的""是正确的.这修复了我的例子,但我的真实代码仍然存在问题.在下面的代码块中,我调整了我的示例以更好地反映我的实际代码.我选择创建一个更简单的例子,首先认为问题是字符串vars.

这是一个不起作用的示例:)使用dat上面创建的相同数据框.

dv <- colnames(dat)[1]
r2 <- colnames(dat)[2]
# the following loop creates objects r3, r4, r5, and r6
# r5 and r6 are interaction terms
for (v in 3:4) {
  r <- colnames(dat)[v]
  assign(paste("r",v,sep=""),r)
  r <- paste(colnames(dat)[2], colnames(dat)[v], sep="*")
  assign(paste("r",v+2,sep=""),r)
}

# combine r3, r4, r5, and r6 then collapse and remove trailing +
vars2 <- sapply(3:6, function(i) { 
                paste0("r", i, "+")
                })
vars2 <- paste(vars2, collapse = '')
vars2 <- substr(vars2, 1, nchar(vars2)-1)

# concatenate dv, r2 (as a factor), and vars into `eq`
eq <- paste0(dv, " ~ factor(",r2,") +", vars2)
Run Code Online (Sandbox Code Playgroud)

这是问题:

print(eq)
# [1] "v1 ~ factor(v2) +r3+r4+r5+r6"
Run Code Online (Sandbox Code Playgroud)

regression第一个示例不同,eq不会引入列名称(例如,v3).r3保留对象名称(例如).因此,以下lm()命令不起作用.

m2 <- lm(as.formula(eq), data=dat)
Run Code Online (Sandbox Code Playgroud)

Aar*_*ica 53

我看到有几个问题在这里发生.首先,我不认为这是造成任何麻烦,但我们让您的数据帧中的一个步骤,你没有v1通过v4漂浮在全局环境以及数据帧.其次,让v2我们在这里制定一个因素,这样我们就不必再将其作为一个因素来处理.

dat <- data.frame(v1 = rnorm(10),
                  v2 = factor(sample(c(0,1), 10, replace=TRUE)),
                  v3 = rnorm(10),
                  v4 = rnorm(10) )
Run Code Online (Sandbox Code Playgroud)

第一部分现在,对于你的第一部分,它看起来像你想要的:

lm(v1 ~ v2 + v3 + v4, data=dat)
Run Code Online (Sandbox Code Playgroud)

虽然您仍然需要指定响应变量,但这是一种更简单的方法.

lm(v1 ~ ., data=dat)
Run Code Online (Sandbox Code Playgroud)

或者,您当然可以通过粘贴和调用来构建函数lm.

f <- paste(names(dat)[1], "~", paste(names(dat)[-1], collapse=" + "))
# "v1 ~ v2 + v3 + v4"
lm(f, data=dat)
Run Code Online (Sandbox Code Playgroud)

但是,我在这些情况下的偏好是使用do.call,它在将表达式传递给函数之前对表达式求值; 这使得生成的对象更适合调用updateon等函数.比较call输出的部分.

do.call("lm", list(as.formula(f), data=as.name("dat")))
Run Code Online (Sandbox Code Playgroud)

第二部分关于你的第二个部分,它看起来这是你要的内容:

lm(factor(v2) + v3 + v4 + v2*v3 + v2*v4, data=dat)
Run Code Online (Sandbox Code Playgroud)

首先,因为v2是数据框中的一个因素,我们不需要那个部分,其次,这可以通过更好地使用R的方法来使用算术运算来创建交互来进一步简化,就像这样.

lm(v1 ~ v2*(v3 + v4), data=dat)
Run Code Online (Sandbox Code Playgroud)

然后,我只需使用创建函数paste; assign即使在较大的情况下,循环也许不是一个好主意.

f <- paste(names(dat)[1], "~", names(dat)[2], "* (", 
           paste(names(dat)[-c(1:2)], collapse=" + "), ")")
# "v1 ~ v2 * ( v3 + v4 )"
Run Code Online (Sandbox Code Playgroud)

然后可以lm直接使用或使用do.call.

lm(f, data=dat)
do.call("lm", list(as.formula(f), data=as.name("dat")))
Run Code Online (Sandbox Code Playgroud)

关于你的代码你试图使用r3等的问题是你想要变量的内容r3,而不是值r3.为了获得价值,你需要get像这样,然后你将这些价值一起折叠paste.

vars <- sapply(paste0("r", 3:6), get)
paste(vars, collapse=" + ")
Run Code Online (Sandbox Code Playgroud)

但是,更好的方法是避免assign和只是构建一个你想要的术语的向量,就像这样.

vars <- NULL
for (v in 3:4) {
  vars <- c(vars, colnames(dat)[v], paste(colnames(dat)[2], 
                                          colnames(dat)[v], sep="*"))
}
paste(vars, collapse=" + ")
Run Code Online (Sandbox Code Playgroud)

将使用更像R的解决方案lapply:

vars <- unlist(lapply(colnames(dat)[3:4], 
                      function(x) c(x, paste(colnames(dat)[2], x, sep="*"))))
Run Code Online (Sandbox Code Playgroud)


Tra*_*ter 6

TL;DR:使用paste.

create_ctree <- function(col){
    myFormula <- paste(col, "~.", collapse="")
    ctree(myFormula, data)
}
create_ctree("class")
Run Code Online (Sandbox Code Playgroud)