【问题标题】:R Error in model.frame.default - Variable lengths differR模型中的错误.frame.default - 可变长度不同
【发布时间】:2022-01-16 06:54:05
【问题描述】:

也是第一次发帖,这只是我第二次使用R,所以请温柔。

我正在做一个项目,我在 R 中尝试通过 lmer 函数使用 lme4 和 lmeTest 包进行多项分析。为此,我列出了要分析的变量名称列表,我使用 for 循环进行迭代。因此它看起来像这样:

list <- MyList of IDs
raw <- My Data File

for (i in list) {
  model <- lmer (`i` ~ Time + SecretorStatus + BioRep + TechRep + (1|Random), data = raw)
  .
  .
  .
  Do something..
  .
  .
}

然而这会产生这个错误:

Error in model.frame.default(data = raw, drop.unused.levels = TRUE, formula = paste(i) ~  : 
  variable lengths differ (found for 'Time')

我很确定该问题与 lmer 声明有关,可能与 i 以及每当我手动将值复制到 i 的位置时一切正常。但是,由于“列表”中有很多值,我需要某种循环。

我在谷歌上搜索了很多,并在这里找到了几个试图解决相同/相似问题的答案,但对我来说它们不起作用。下面是一些更好的解决方案的链接列表,但是它们并没有解决我的问题。

谁能提供一些关于这种现象的见解?

编辑 1 - @r2evans 要求提供可重现的示例。这在下面提供。

#Packages used
library(Matrix) 
library(lme4)
library(lmerTest)
library(stringr)
library(readr)
#Starting to read data
rootDir <- getwd()
raw <- read.csv(str_c(rootDir, "/P035aForR.csv"), na = c("", "NA", "0"))
list <- read.csv(str_c(rootDir, "/P035aHeaddersForR2.csv"), na = c("", "NA", "0"), header = FALSE)
#Generate dir for output and the dataframe to store the main results
dir.create("Results", showWarnings = TRUE, recursive = FALSE, mode = "0777")
dir.create("Results/Data", showWarnings = TRUE, recursive = FALSE, mode = "0777")
dir.create("Results/Pictures", showWarnings = TRUE, recursive = FALSE, mode = "0777")
dir.create("Results/Pictures/QQPlot", showWarnings = TRUE, recursive = FALSE, mode = "0777")
dir.create("Results/Pictures/RawResiduals", showWarnings = TRUE, recursive = FALSE, mode = "0777")
dir.create("Results/Pictures/PersonResiduals", showWarnings = TRUE, recursive = FALSE, mode = "0777")
Result <- data.frame("","","","","","")
names(Result)<-c("ID","SecretorStatus","Time","BioRep","TechRep","Shapiro") ### <-- Update the headders as needed
Result <- Result[-c(1),]
#Load variables from raw as factors for the analysis
raw$SecretorStatus <- as.factor(raw$SecretorStatus)
raw$Time <- as.factor(raw$Time)
raw$TechRep <- as.factor(raw$TechRep)
raw$BioRep <- as.factor(raw$BioRep)
raw$Random <- as.factor(raw$Random)
for (i in list) {
  model <- lmer (`i` ~ Time + SecretorStatus + BioRep + TechRep + (1|Random), data = raw) 
  anova <- as.data.frame(anova(model, type = 2),) 
  residuals <- residuals(model, "response")
  pvalue <- round(shapiro.test(residuals)$p.value, digits=4 ) 
  out <- as.data.frame(anova(model, type = 2))
  write.table(out, "Results/Data/i.txt", col.names=T, row.names=T, quote=F, sep=",")
  png(Results/Pictures/QQPlot/i.png)
  qqnorm(residuals, sub=paste("p-value of a Shapiro-Wilks test =", pvalue )); qqline(residuals) 
  dev.off()
  Pearson.Residuals <- residuals(model, "pearson")
  Raw.Residuals <- residuals(model, "response")
  Fitted <- fitted(model)
  png(Results/Pictures/RAWResiduals/i.png)
  plot(Fitted, Raw.Residuals, main=i)
  dev.off()
  png(Results/Pictures/PersonResiduals/i.png)
  plot(Fitted,Pearson.Residuals, main=i)
  dev.off()
  tmp <- data.frame(i, pvalue, t(anova[,"Pr(>F)"]))
  names(tmp) <- c("ID", "Shapiro", row.names(anova))
  Result <- rbind(Result, tmp)
}

此时在它说的地方生成错误:

Error in model.frame.default(data = raw, drop.unused.levels = TRUE, formula = i ~  : 
  variable lengths differ (found for 'Time')

关于数据的设置,我无法提供完整的数据集(显然),但是下面提供了一个演示结构的示例。这是原始变量的数据。

SecretorStatus  Time    TechRep BioRep  Random  ID1 ID2 ID3 ID4 ID5 ID6 ID7 ID8 ID9 ID10    ID11    ID12    ID13    ID14    ID15    ID16
1   1   1   1   1   23342.99    23342.99    0   0   0   0   0   0   0   0   0   0   102829.8    492252.5    0   924436.3
2   1   2   5   2   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   529782
2   1   1   6   3   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   506987.7
2   1   2   6   4   0   0   0   0   0   0   0   0   0   0   0   0   0   48786.41    0   618768.5
1   1   2   1   1   0   0   0   0   0   0   0   0   0   0   0   0   0   414852.1    354153.5    850788.9
1   1   1   2   2   0   0   0   0   0   0   0   0   0   99551.51    0   0   322185.6    0   361100.2    819073.6
1   1   2   2   3   0   0   0   0   0   90194.2 0   0   0   73646.15    0   0   0   398369.2    277569.9    613257.3
1   1   1   3   4   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
1   1   2   3   1   0   0   0   0   0   0   0   0   0   0   0   0   0   265760.8    0   0
2   1   1   4   2   0   0   0   0   0   0   0   0   0   0   0   0   61351.9 554385.9    0   656984.3
2   1   2   4   3   0   0   0   0   0   0   0   0   0   0   0   0   0   622428.4    0   769227.8
2   1   1   5   4   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   388584.9
1   2   1   1   1   31454.26    31454.26    0   0   0   0   0   0   0   0   0   0   0   0   0   729234.2
1   2   2   1   2   0   0   0   0   0   0   0   0   0   0   0   0   0   333620.4    0   933046.3
1   2   1   2   3   0   0   0   0   0   0   0   0   0   0   0   0   0   834145.3    0   0
1   2   2   2   4   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   157152.7
1   2   1   3   1   0   0   0   0   0   0   0   0   0   0   0   0   0   178179.3    0   812282.9
1   2   2   3   2   0   0   0   0   0   86782.91    0   0   0   0   0   0   0   191167  0   663968.9
2   2   1   4   3   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   610315.3
2   2   2   4   4   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   339407.1
2   2   1   5   1   0   0   0   0   0   0   0   0   0   213881.1    0   0   0   0   0   298894.5
2   2   2   5   2   0   0   0   0   0   0   0   0   0   81122.63    0   0   0   0   0   170576.6
2   2   1   6   3   0   0   0   0   0   0   0   0   0   53790.86    0   0   0   0   0   205826
2   2   2   6   4   0   0   0   0   0   37900.34    0   0   0   0   0   0   0   0   315754  232529.7

对于列表中的数据,上述示例数据的数据结构将是。

ID1 ID2 ID3 ID4 ID5 ID6 ID7 ID8 ID9 ID10    ID11    ID12    ID13    ID14    ID15    ID16

包含 raw 和 list 数据的两个文件都是 csv 文件。 在整个过程中,只产生了一个错误(至少在我的结尾)。但是,如果您执行两次代码,它会抱怨文件夹已经存在。但是,除此之外它只会产生一个错误。 我注意到的另一个细节是变量i 在发生此错误时卡在 ID1,因此它不会浏览整个列表,它在第一个对象处失败。 我希望这有助于澄清。如果您想要/需要重现错误的更多详细信息,请告诉我。

【问题讨论】:

  • 欢迎来到 SO,MNTsnowman!请让这个问题可重现。这包括您尝试过的示例代码(包括列出非基础 R 包以及收到的任何错误/警告)、示例明确数据(例如,data.frame(x=...,y=...) 或来自dput(head(x)) 的输出),和给定输入的预期输出。参考:stackoverflow.com/q/5963269、minimal reproducible example 和 stackoverflow.com/tags/r/info。 (仅供参考,以list 和raw 等常见基函数命名对象通常是不好的做法。虽然 R 经常做正确的事情,但它会使阅读他人的代码变得更加困难。)
  • 请提供足够的代码,以便其他人更好地理解或重现问题。
  • 嗨@r2evans,已添加一个可重现的示例作为对原始帖子的编辑。我希望这有帮助。如果您还需要什么,请告诉我。
  • 这不是最小的(绘图、残差、目录创建等都与问题 AFAICS 无关)...

标签: r lme4 lmertest


【解决方案1】:

从您给我们的内容中很难判断,但我认为应该这样做:

pred_vars <- c("Time", "SecretorStatus", "BioRep", "TechRep", "(1|Random)")
list_of_IDs <- names(raw)[startsWith(names(raw), "ID")]
for (i in list_of_IDs) {
  f <- reformulate(pred_vars, response = i)
  model <- lmer (f, data = raw)
  ## ...
}

您实际上并不需要reformulate,您也可以使用paste 或sprintf 或任何其他字符串操作机制将您的公式作为字符串放在一起,然后应用as.formula(),但reformulate更好一点。

一个稍微更有效的解决方案将使用refit():

for (i in list_of_IDs) {
   if (i == list_of_IDs[1]) {
      model <- lmer (ID1 ~ Time + SecretorStatus + BioRep + TechRep + (1|Random), 
                     data = raw)
   } else {
      model <- refit(model, newresp = raw[[i]])
   }
   ## ...

}

正如?refit 中所述,“‘refit()’方法应该更快,因为它绕过了模型表示的创建并直接进入优化步骤。”

【讨论】:

  • 嗨@Ben Bolker,非常感谢您的回复。已在原始帖子中添加了一个编辑,其中包含更多信息,我希望这能澄清我正在尝试做的事情。关于您的两个建议,第一个提供了此错误“错误:分组因子必须具有> 1个采样级别”,这可能与数据结构有关吗? (2 个中的第 1 个)
  • 第二个建议提供了此错误“评估中的错误(predvars,data,env):找不到对象'first_variable'另外:警告消息:在if(i == list){:条件长度 > 1 并且只使用第一个元素”,然后我在 first_variable 的位置插入第一个变量的名称,产生的错误是这个“错误:分组因子必须具有 > 1 个采样级别另外:警告消息: 在 if (i == list2) { : 条件的长度 > 1 并且只使用第一个元素”(答案 2 of 2)
  • 我上面的两个示例都使用上面的示例数据运行(我确实收到了警告,但它们可能是由于给定数据的一小部分)。如果您需要更多帮助,您将需要缩小错误来源(可能会问一个新问题);我真的不想亲自挖掘你所有的代码......
  • PS first_variable 错误是因为你应该用你的第一个 ID 变量的名称填写它。我现在已经这样做了。无法帮助您解决第一个错误(请注意,它与您最初寻求帮助的错误不同......)
猜你喜欢
  • 2016-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多