在下面的最小示例中,我尝试在回归公式中使用字符串 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)
更新:
@Arun 关于第一个示例中 v1
上缺少的“”是正确的。这修复了我的示例,但我的实际代码仍然存在问题。在下面的代码块中,我调整了示例以更好地反射(reflect)我的实际代码。我一开始认为问题出在字符串 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)
问题是这样的:
print(eq)
# [1] "v1 ~ factor(v2) +r3+r4+r5+r6"
与第一个示例中的回归
不同,eq
不会引入列名称(例如v3
)。对象名称(例如,r3
)被保留。因此,以下 lm()
命令不起作用。
m2 <- lm(as.formula(eq), data=dat)
最佳答案
我发现这里出现了几个问题。首先,我认为这不会造成任何麻烦,但让我们一步创建数据框,这样就不会在 v1
到 v4
中 float 全局环境以及数据框架。其次,让我们在这里将 v2
作为一个因素,这样我们就不必在以后处理将其作为一个因素的问题。
dat <- data.frame(v1 = rnorm(10),
v2 = factor(sample(c(0,1), 10, replace=TRUE)),
v3 = rnorm(10),
v4 = rnorm(10) )
第一部分现在,对于您的第一部分,看起来这就是您想要的:
lm(v1 ~ v2 + v3 + v4, data=dat)
这是一种更简单的方法,但您仍然需要指定响应变量。
lm(v1 ~ ., data=dat)
或者,您当然可以使用粘贴来构建该函数并在其上调用lm
。
f <- paste(names(dat)[1], "~", paste(names(dat)[-1], collapse=" + "))
# "v1 ~ v2 + v3 + v4"
lm(f, data=dat)
但是,在这些情况下我更喜欢使用do.call
,它在将表达式传递给函数之前对其进行计算;这使得生成的对象更适合调用诸如 update
之类的函数。比较输出的 call
部分。
do.call("lm", list(as.formula(f), data=as.name("dat")))
第二部分关于你的第二部分,看起来这就是你想要的:
lm(factor(v2) + v3 + v4 + v2*v3 + v2*v4, data=dat)
首先,因为 v2
是数据框中的一个因素,所以我们不需要该部分,其次,可以通过更好地使用 R 的算术运算方法来创建交互来进一步简化这一点,像这样。
lm(v1 ~ v2*(v3 + v4), data=dat)
然后我只需使用 paste
创建该函数;即使在较大的情况下,带有 assign
的循环也可能不是一个好主意。
f <- paste(names(dat)[1], "~", names(dat)[2], "* (",
paste(names(dat)[-c(1:2)], collapse=" + "), ")")
# "v1 ~ v2 * ( v3 + v4 )"
然后可以直接使用 lm
或使用 do.call
调用它。
lm(f, data=dat)
do.call("lm", list(as.formula(f), data=as.name("dat")))
关于您的代码您在尝试使用r3
等时遇到的问题是您想要变量r3
的内容,而不是值r3
。要获取该值,您需要像这样 get
,然后使用 paste
将这些值折叠在一起。
vars <- sapply(paste0("r", 3:6), get)
paste(vars, collapse=" + ")
但是,更好的方法是避免分配
并仅构建所需术语的向量,如下所示。
vars <- NULL
for (v in 3:4) {
vars <- c(vars, colnames(dat)[v], paste(colnames(dat)[2],
colnames(dat)[v], sep="*"))
}
paste(vars, collapse=" + ")
一个更像 R 的解决方案是使用 lapply
:
vars <- unlist(lapply(colnames(dat)[3:4],
function(x) c(x, paste(colnames(dat)[2], x, sep="*"))))
关于r - 如何在公式中使用字符串引用变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17024685/