簡體   English   中英

如何在公式中通過字符串使用引用變量?

[英]How to use reference variables by character string in a formula?

在下面的最小示例中,我嘗試在回歸公式中使用字符串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上缺少的 "" 是正確的。 這修復了我的示例,但我的真實代碼仍然存在問題。 在下面的代碼塊中,我修改了我的示例以更好地反映我的實際代碼。 我選擇創建一個更簡單的示例,起初認為問題出在字符串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"

與第一個示例中的regression不同, eq不會引入列名(例如, v3 )。 對象名稱(例如, r3 )被保留。 因此,以下lm()命令不起作用。

m2 <- lm(as.formula(eq), data=dat)

我看到這里有幾個問題。 首先,我不認為這會造成任何問題,但是讓我們一步一步地制作數據框,這樣您就不會在全局環境和數據框中都有v1v4浮動。 其次,讓我們在這里將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)

或者,您當然可以使用 paste 構建函數並在其上調用lm

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

但是,在這些情況下,我更喜歡使用do.call ,它在將表達式傳遞給函數之前評估它們; 這使得生成的對象更適合調用update on 等函數。 比較輸出的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=" + ")

但是,更好的方法是避免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=" + ")

更像 R 的解決方案是使用lapply

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

TL;DR:使用paste

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM