【问题标题】:Correspond Indicator Matrix to Column Names in R将指示符矩阵对应于 R 中的列名
【发布时间】:2020-04-20 20:33:51
【问题描述】:

我要解决的问题是“如何创建一系列自动化代码,从数据集中提取所需的列标题名称以适应一般线性化模型 (glm)?”我有一个包含 8 个变量的数据集;但是,我只想使用其中的 3 个来交叉验证并找到“最佳”模型。这是我想出的:

library(boot)
salary <- read.csv("salary_data.csv")
vars <- colnames(salary[c(2,3,7)])
nvars <- length(vars)
list.to.expand = vector(mode = "list", length = nvars)
for (i in 1:nvars){
  list.to.expand[[i]]=c(0,1)
}
model.spec.matrix <- expand.grid(list.to.expand)
vars
model.spec.matrix
names(model.spec.matrix) <- vars
vars.to.use <- model.spec.matrix[2,]
vars.to.use <- as.numeric(vars.to.use)
cn <- c()
for (i in 1:nrow(model.spec.matrix)){
  if(i==1){cn <- colnames(model.spec.matrix[sapply(model.spec.matrix[i,], function(x) x > 0)]) 
  }
}
print(cn)
paste(cn, collapse = "+")
glm.out = glm(paste("LogACG~",paste(cn,collapse = "+"),sep = ""), family = gaussian, data = salary)
cv.err = cv.glm(salary, glm.out, K = 10)$delta[1]

我的问题在于 for 循环。我试图构建一个循环,它将“vars”中的值附加到“model.use”中,但我似乎无法让它读取矩阵中的第二行。有什么建议么?谢谢

【问题讨论】:

  • 我会删除我在答案中给你的代码,以便问题和答案仍然有意义。你在第一行得到character(0) 的原因是矩阵的第一行没有指定的列(0 0 0)所以这就是为什么我在它后面加上一行(if(length(cn) == 0){cn &lt;- "."}

标签: r for-loop if-statement cross-validation


【解决方案1】:

这里似乎发生了几件事。

您已将 LogACG 设置为倒数第二行 ("LogACG~,但它也是 vars 之一,由于 vars &lt;- colnames(salary[c(2,3,7)]),它最终以 model.vars 结尾,所以这是不对的。

接下来你的第二个for 循环应该遍历model.spec.matrix 的行,即

for(i in 1:nrow(model.spec.matrix)){

并以编程方式捕获您可以执行的该行指示的列名(变量)

cn &lt;- colnames(model.spec.matrix[sapply(model.spec.matrix[i,], function(x) x &gt; 0)])

在循环中。您还应该将glmcv.glm 移动到循环内。

但是,这将覆盖 glm.outcv.err 每次,因此您需要将它们创建为空列表并在每次迭代中附加列表。

所以最终产品将如下所示:

# Since you can't use LogACG to explain itself, 
#    suppose you meant to use Engineering as a candidate X
vars <- colnames(salary[c(2,3,8)])

# Make your grid
model.spec.matrix        <- expand.grid(list.to.expand)
names(model.spec.matrix) <- vars

glm.out <- list(rep(NA, nrow(model.spec.matrix)))
cv.err  <- list(rep(NA, nrow(model.spec.matrix)))

for(i in 1:nrow(model.spec.matrix)){
  cn <- colnames(model.spec.matrix[sapply(model.spec.matrix[i,], function(x) x > 0)])
  if(length(cn) == 0){cn <- "."}  
  tmp        <- glm(as.formula(paste("LogACG~",paste(cn,collapse = "+"),sep = "")), family = gaussian, data = salary)
  glm.out[i] <- capture.output(tmp$formula)
}
# > glm.out
# [[1]]
# [1] "LogACG ~ ."
# 
# [[2]]
# [1] "LogACG ~ Rank_Code"
# 
# [[3]]
# [1] "LogACG ~ Gender"
# 
# [[4]]
# [1] "LogACG ~ Rank_Code + Gender"
# 
# [[5]]
# [1] "LogACG ~ Engineering"
# 
# [[6]]
# [1] "LogACG ~ Rank_Code + Engineering"
# 
# [[7]]
# [1] "LogACG ~ Gender + Engineering"
# 
# [[8]]
# [1] "LogACG ~ Rank_Code + Gender + Engineering"

要获取列表元素中的整个模型对象,请替换

glm.out[i] <- capture.output(tmp$formula)

glm.out    <- append(glm.out, tmp)

for(i in 1:nrow(model.spec.matrix)){
  cn <- colnames(model.spec.matrix[sapply(model.spec.matrix[i,], function(x) x > 0)])
  if(length(cn) == 0){cn <- "."}  
  tmp        <- glm(as.formula(paste("LogACG~",paste(cn,collapse = "+"),sep = "")), family = gaussian, data = salary)
  tmp1       <- cv.glm(salary, tmp, K = 10)$delta[1]
  glm.out    <- append(glm.out, tmp)
  cv.err     <- append(cv.err, tmp1)
}

> tail(cv.err)
[[1]]
[1] 2.751025

[[2]]
[1] 2.758954

[[3]]
[1] 2.735063

[[4]]
[1] 2.768075

[[5]]
[1] 2.774433

[[6]]
[1] 2.748291

此外,您最好使用bestglm 之类的包,或仅使用默认包stats 中的step 函数(请参阅?step)。

【讨论】:

  • 是的,我同意你的看法,看看它是如何工作的。但是,我必须能够自动化代码,这样,如果我拉入一个包含 100 个变量的数据集,我就可以轻松地拉出我想要使用的变量并将它们粘贴到 glm 中。提供的 glm 函数需要我每次都重写它,这是我试图避免的。谢谢
  • 我用您在响应中创建的 cn 变量替换了 model.vars 变量。但是,当我运行 for 循环时,cn 变量在我打印时返回 character(0)。在问题中查看我上面编辑的代码。谢谢
  • 知道了。谢谢!
  • 因此,如果我想显示上述代码中每个可能模型的误差项图,我该怎么做?我想确定只有主效应的所有模型中的最小误差(通过根据带有 1 和 0 的 model.spec.matrix 行包括和排除变量)。
  • 太完美了。感谢您的所有帮助,我无法告诉您我有多感激。还有一件事:那么我如何从 glm.out 到 cv.glm 运行这些模型并将错误存储在向量中?
猜你喜欢
  • 2019-04-05
  • 2021-10-19
  • 2015-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多