【问题标题】:How to run a for loop to run regressions by dummy variables如何运行 for 循环以通过虚拟变量运行回归
【发布时间】:2019-12-30 22:41:27
【问题描述】:

我有以下代码:

reg <- lm(Y ~ x1 + x1_sq + x2 + x2_sq + x1x2 + d2 + d3 + d4, df)

其中所有 x_i 都是连续变量,d_i 是互斥虚拟变量(d1 存在但排除以避免完美的多重共线性)。我不想包括虚拟变量,而是想对每个虚拟变量 == 1 运行单独的回归。我希望通过以下形式的循环来实现这一点:

dummylist <- list("d1", "d2", "d3", "d4")
for(i in dummylist){
   if(i==1){
      ireg <- lm(Y ~ x1 + x1_sq + x2 + x2_sq + x1x2, df)
   } else {
      Unsure what to put here
   }
}

我的三个(?)问题是:

  1. 在 -if- 函数的第一部分,我是否只在“reg”之前包含“i”,以便我的代码生成结果“d1reg、d2reg 等”?并且,
  2. 包含在上面的代码中,我应该在 -else- 语句之后添加什么?
  3. 这一切都引出了一个问题,将 if-else 语句 within 放在 -for- 循环中是错误的方法/是否有更合适的循环?

对不起,如果这太多了,请告诉我是否是这样,我可以将其删减或分成多个问题。我找不到类似的问题,可能是因为我对在 R 中运行循环比较陌生,不知道要寻找什么。

【问题讨论】:

  • 是的,去掉 ifelse ,因为你不希望该回归有任何假人 - 只需在循环外运行它,然后从列表中删除 d1 。 (目前,i == 1 永远不会为真;i 是“d1”、“d2”、“d3”或“d4”,但绝不是 1。)不,您不能只将 i 添加到变量名中。但是您可以在循环之前执行regs &lt;- list(),然后在其中执行regs[[i]] &lt;- lm(...)。一般来说,如果你有很多相似的东西,你应该把它们放在一个列表中,而不是放在几个名称相似的变量中。

标签: r for-loop if-statement linear-regression dummy-variable


【解决方案1】:
  1. 在 -if- 函数的第一部分,我是否只在“reg”之前包含“i”,以便我的代码生成结果“d1reg、d2reg 等”?

短:

在 R 中有许多数据类型。其中一个更通用的曾经是list 对象,它可以存储任何类型的对象。或者,可以创建一个environment 来存储其中的列表,但这有点矫枉过正。

如果您大致知道列表中应该包含多少元素,最简单的方法是在循环之前将其初始化为

n <- 3
regList <- vector(mode = "list", length = n)
# Optional naming:
#names(regList) <- c("d1 reg", "d2 reg", "d3 reg")

在您的循环中,您然后迭代地填写您的列表:

for(i in seq_along(regList)){
   regList[[i]] <- lm(...)
}
  1. 在 -else- 语句之后应该放什么?这一切都引出了问题,

这里并不完全清楚你想要什么。要么你想“只”包括单独的虚拟变量。为此,最简单的方法可能是保存您的 formula 并迭代更新它。

form <- Y ~ x1 + x1_sq + x2 + x2_sq + x1x2
for(i in seq_along(regList)){
   #paste0 combine strings. ". ~ . + d1" means take the formula and add the element d1 
   form <- update(form, as.formula(paste0(". ~ . + d", i)) 
   regList[[i]] <- lm(form, data = df)
}

或者您实际上是在尝试对 d[i] == 1 所在的子集运行单独的回归。这实际上可以通过lm 本身来完成

form <- Y ~ x1 + x1_sq + x2 + x2_sq + x1x2
d <- list(d1, d2, d3)
for(i in seq_along(regList)){
   #Using the subset argument
   regList[[i]] <- lm(form, data = df, subset = which(d[[i]] == 1))
   #Alternatively:
   #regList[[i]] <- lm(form, data = subset(df, d[[i]] == 1))
}

免责声明: d1、d2、d3 是否是 df 的一部分并不完全清楚。在这种情况下,下面的示例将起作用

   regList[[i]] <- with(df, lm(form, subset = which(d[[i]] == 1)))
  1. 在 -for- 循环中放置 if-else 语句是错误的方法/是否有更合适的循环?

在这种情况下,这显然不是正确的方法。但这在所有情况下都不是错误的方法。在这里,它只是没有明确的目的。请注意,i in dummylist 将返回 "d1", "d2", "d3", "d4",因为变量已被引用,而不是直接放在列表中。

但是要解决的另一件事是,在执行线性回归之前,您是否自己转换了变量。请注意R 的内部函数允许您直接在formula 中执行此操作,这样做可以帮助您避免错误错误,例如测试存在交互的变量,除非它非常非常很多你想做的事。例如我假设x1_sq = x1^2。也许d1, d2, d3 都包含在变量d 中?在这些情况下,您应该使用如下所示的原始变量:

lm(formula = Y ~ poly(x1, 2, raw = TRUE) + poly(x2, 2, raw = TRUE) + x1:x2, data = df ) #+d if d1, d2, d3 is part of the formula

poly 是二阶多项式,raw = TRUE 返回参数为x1 + I(x1^2) 而不是正交表示。

如果这样做,drop1anova 等的输出将考虑到它不应该测试一阶变量到二阶交互。

【讨论】:

  • 我有 4 个虚拟变量,我想对 d1==1 和所有其他 ==0,然后 d2==1 和所有其他 ==0,...等等。它们是作物(小麦、大米等)的虚拟变量,我想先进行小麦回归,然后再进行水稻回归……等等。我想我可以从中解决,非常感谢。
  • 另外,你是正确的,我的 d1、d2、d3 包含在 string 变量 d 中。我刚刚为字符串 d 的每个值创建了虚拟变量。这是在我练习 R 时完成的,我的常规软件包是 Stata,我想在 R 上做得更好
  • @Brennan (1) 那是我的赌注。 Stata(我也相信 SAS)需要显式创建虚拟变量,其中 R 的实现会自动处理序数和名义因子变量。我建议不要创建自己的变量,而是直接通过 formula 类执行大多数转换。例如y~log(x) + x*z 将生成y = log(x) + x + z + x:zpoly(x,2) 创建x + x^2(尽管除非指定raw=TRUE,否则会正交化)。如果d 包含您的虚拟对象,您可以按d == "d1" 或适当的值进行子集化。
  • (2) 我还没有找到足够好的公式概述和解释,但基础是:+ 按原样添加一个术语。 - 从现有公式中删除一个术语 -1 删除截距。 : 创建交互 * 创建交互加上加法效果 | 让您可以模拟类似于 a + a:b 的条件。像log(x) 这样的某些表达式按预期工作,但更复杂的东西可能需要“按原样”运算符I( ... ) 强制在使用之前对表达式进行评估。例如I(sqrt(x)^(2/3)) 会正确评估,而sqrt(x)^(2/3) 不会。
  • (3) 后者是因为(a+b+c)^2被评估为a+b+c+a:b+a:c+b:c,意味着^n是二阶交互。他的所有内容都在文档中的示例中描述得有些糟糕,甚至更糟糕,可以通过在 R 中执行 help(formula) 来获得。我希望这会有所帮助,否则 SO 是找到问题答案的好地方当Stata有时不够时经常弹出。
猜你喜欢
  • 1970-01-01
  • 2021-02-18
  • 1970-01-01
  • 2019-05-22
  • 2016-07-18
  • 2021-05-27
  • 2019-10-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多