【问题标题】:lm() looped over factor variable while dropping single-level factor variables from the modellm() 循环遍历因子变量,同时从模型中删除单级因子变量
【发布时间】:2020-12-07 00:32:50
【问题描述】:

我有一个数据集,我试图在其中循环一个因子变量 (location) 并为该因子的每个级别构建一个单独的模型。但是,根据location,存在单级因子变量,这给了我这个错误:

Error in `contrasts<-`(`*tmp*`, value = contr.funs[1 + isOF[nn]]) : 
  contrasts can be applied only to factors with 2 or more levels
Called from: `contrasts<-`(`*tmp*`, value = contr.funs[1 + isOF[nn]])

因此,根据location,我想从模型中删除任何单级因子。我尝试将数据拆分为一个没有任何单级因子的数据集和另一个没有任何单级因子的数据集,但我不知道如何根据位置删除给定的因子变量。

这会给你错误:

library(data.table)

dt <- data.table(df, key = "location")
lapply(unique(dt$location), function(z) lm(y ~ x1 + x2 + x3 + x4 + x5, data = dt[J(z),]))

不过,我对 data.table 不太满意,因此任何非 data.table 解决方案都会非常有用。谢谢。

一些数据:


y <- rnorm(n = 100, mean = 50, 5) 
x1 <- rnorm(n = 100, mean = 10, sd = 3)                                         
location <- factor(c(rep(1, 20), rep(2, 20), rep(3, 20), rep(4, 20), rep(5, 20)))
x2 <- rnorm(n = 100, mean = 25, sd = 3)
x3 <- factor(sample(c(0, 1), size = 100, replace = TRUE))
x4 <- factor(ifelse(location == 1, 0, 
                ifelse(location == 2, sample(c(0, 1), size = 20, replace = TRUE), 
                       ifelse(location == 3, 1, 
                              ifelse(location == 4, 0, sample(c(0, 1), size = 20, replace = TRUE))))))
x5 <- factor(ifelse(location == 1, sample(c(0, 1), size = 20, replace = TRUE),
                     ifelse(location == 2, 1, 
                            ifelse(location == 3, sample(c(0, 1), size = 20, replace = TRUE),  
                                   ifelse(location == 4, sample(c(0, 1), size = 20, replace = TRUE), 0)))))

df <- data.frame(y, location, x1, x2, x3, x4, x5) 

【问题讨论】:

  • 我尝试为每个位置级别运行您的 lm(...) 公式。我认为您遇到了“对比”错误,因为您的某些 x4x5 因素在每个位置没有两个或更多级别。例如,如果我运行lapply(unique(df$location), function(z) lm(y ~ x1 + x2 + x3, data = df[df$location==z,])),则它可以工作,但如果我运行lapply(unique(df$location), function(z) lm(y ~ x1 + x2 + x3 + x4, data = df[df$location==z,])),则它不会工作,后者包括+ x4
  • 是的,正是,我创建了示例数据来做到这一点。对不起,如果我的帖子不清楚。我得到了对比度错误,因为某些因子变量没有两个或更多级别,具体取决于位置。对于每个具有单级因子变量的位置,我想从该位置的模型中删除该因子变量。
  • 哦,我想我可能看错了。我之前在另一个线程上发布了一个可能有帮助的解决方案:stackoverflow.com/a/64801181/6288065。这里的解决方案可能不需要其中的某些部分,但我认为如何通过不同的模型运行lapply() 的要点就在那里。如果不清楚,请告诉我。我可以在这里为您重新制定解决方案。
  • 谢谢。我一直在尝试使用 lapply() 但实际数据集有两个以上“有问题”的因子变量,所以我一直在努力弄清楚。

标签: r


【解决方案1】:

您的模型的公式取决于每个自变量中是否有足够的水平被包含在内。

您可以根据这些条件创建一个公式(例如,使用ifelse()),然后将公式输入到lapply() 内部的模型中。

这里有一个解决方案:

lapply(unique(df$location), function(z) {
    sub_df = dplyr::filter(df, location == z) # subset by location
    form_x4 = ifelse(length(unique(sub_df$x4)) > 1, "+ x4", "")
    form_x5 = ifelse(length(unique(sub_df$x5)) > 1, "+ x5", "")
    form = as.formula(paste("y ~ x1 + x2 + x3", form_x4, form_x5))
    return(lm(data = sub_df, formula = form))
})

上述lapply(...)中的formlm()公式的一致部分与多个满足公式中使用条件的变量组合在一起。如果变量只有一个级别,ifelse() 语句允许您在将其放入公式时将其视为不存在。

【讨论】:

  • 谢谢!我能够在实际数据上使用它。有没有办法从模型摘要中知道哪个模型对应于哪个位置?
  • 显示每个模型位置的最简单方法是在lapply(...) 中包含print(z)。否则,如果您想要更容易使用的东西,您可能需要创建模型的自定义汇总表/数据框,如stackoverflow.com/a/64801181/6288065 中所示。您可以将位置添加为表格中的列。
猜你喜欢
  • 1970-01-01
  • 2021-04-21
  • 2020-08-24
  • 1970-01-01
  • 2018-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多