【问题标题】:Repeat entry in data.frame filled from for() loop在从 for() 循环填充的 data.frame 中重复输入
【发布时间】:2016-02-07 01:02:09
【问题描述】:

我有一个数据集,其中包含个人和年份的观察结果。我想将数据隔离到每个人。在每个人中,我想为每年拟合多个模型。然后,我想将每个单独年份模型的 AIC 分数编译为 data.frame,然后将其保存在一个列表中。

我使用iris 数据在下面创建了一个可重现的示例。我正在使用嵌套的 for 循环将数据子集到个人 (i) 和年份 (j)。

问题:有些物种有三年的数据(例如 setosa 和 versicolor),而维吉尼亚只有一年的数据(2014 年)。

当物种data.frames被添加到列表中时,少于三年的物种包含前几年的重复记录。从下面的结果中可以看出,list[[3]] 应该包含 2014 年Virginica 物种的单行数据,而不是 2011 年和 2012 年 versicolor 的重复记录。

是否可以有一个具有不同行数的data.frames 列表?

我欢迎任何改进嵌套 for 循环的建议。我怀疑有更好的方法可以做到这一点,也许是dplyr

head(iris)

#Add year to iris to reproduce problem
iris$Year <- c(rep(c("2011", "2012", "2013"), len = 100), rep("2014", 50))

#Make list of species of index and empty list
Sp <- unique(iris$Species)
ResultsList <- list()

#make Results table
AICTbl <- data.frame(Species = as.character(), AIC_1 = numeric(), AIC_2 = numeric(), stringsAsFactors=FALSE)

#run nested for loop
for(i in 1:length(Sp)) {
  SpeciesDat <- subset(iris, Species == Sp[i])

  for(j in 1:length(unique(SpeciesDat$Year))) {
    Years <- unique(SpeciesDat$Year)
    datasub <- SpeciesDat[SpeciesDat$Year == Years[j] , ]

    #Make the animal Year rowID
    AICTbl[j,1] = paste(Sp[i] , Years[j], sep = "_")

    mod.1 <- lm(Sepal.Length ~ Sepal.Width, data = datasub)
    AICTbl[j,2] = AIC(mod.1)

    mod.2 <- lm(Sepal.Length ~ Petal.Length, data = datasub)
    AICTbl[j,3] = AIC(mod.2)

          }
        ResultsList[[i]] <- AICTbl
    }


> ResultsList
[[1]]
      Species    AIC_1     AIC_2
1 setosa_2011 3.649775 21.089619
2 setosa_2012 4.512392  2.280987
3 setosa_2013 4.638183 19.718576

[[2]]
          Species    AIC_1    AIC_2
1 versicolor_2013 25.30007 18.93356
2 versicolor_2011 26.57170 15.22717
3 versicolor_2012 21.62511 11.82291

[[3]]
          Species    AIC_1    AIC_2
1  virginica_2014 89.88263 32.91367
2 versicolor_2011 26.57170 15.22717
3 versicolor_2012 21.62511 11.82291

加法 感谢您的建议和改进@jeremycg。以下添加是延续,尽管您已经回答了 OP。任何其他想法将不胜感激。

我的真实代码的不可重现示例如下所示,其中显示了适合每个 IndID-Year 的 5 个模型之一。

datasub %>% group_by(IndID, Year) %>% 
    do(m.1 = try(nls(NSD ~ (asym/(1+exp((t1 - J_day_new)/dur1)))+(-asym/(1+exp((t2 - J_day_new)/dur2))), 
          control=nls.control(maxiter = 1000, warnOnly=TRUE), algorithm="port",
                  start=c(asym=0.75*max(datasub$NSD), t1=135, t2=285, dur1=2, dur2=2),
              data = datasub),TRUE)

      ) %>%
    mutate(m.1 = AIC(m.1))

如果我将datasub(数据框)替换为.,则会出现以下错误。

Error in UseMethod("logLik") : 
  no applicable method for 'logLik' applied to an object of class "try-error"

【问题讨论】:

  • 用两个变量分割数据框使用split(dataset, dataset[ , c('var1', 'var1')])。它会让你的代码很短。当然,一个列表可以有不同行数的数据框。列表是一个通用向量。示例:df1 &lt;- data.frame(1:3, 4:6); df2 &lt;- data.frame(1:5, 6:10); l1 &lt;- list(df1, df2)。它适用于 R。

标签: r for-loop dplyr


【解决方案1】:

这里有一段相当复杂的代码。我们可以使用dplyr 简化它。如果您要按组进行大量建模,​​您可能还想查看broom 包。

以下是您的代码的较短版本:

library(dplyr)
iris %>% group_by(Species, Year) %>%
         do(mod1 = lm(Sepal.Length ~ Sepal.Width, data = .),
            mod2 = lm(Sepal.Length ~ Petal.Length, data = .)) %>%
         mutate(mod1 = AIC(mod1), mod2 = AIC(mod2))

Source: local data frame [7 x 4]
Groups: <by row>

     Species  Year      mod1      mod2
      (fctr) (chr)     (dbl)     (dbl)
1     setosa  2011  3.649775 21.089619
2     setosa  2012  4.512392  2.280987
3     setosa  2013  4.638183 19.718576
4 versicolor  2011 26.571702 15.227167
5 versicolor  2012 21.625111 11.822912
6 versicolor  2013 25.300073 18.933559
7  virginica  2014 89.882627 32.913666

如果你真的想要它在一个列表中,你可以将上面的输出分配给z,然后按物种分割:

split(z, list(z$Species))

【讨论】:

  • 谢谢。非常有帮助。我一直在阅读“。”但想知道您是否还可以提供其他信息。使用 'data = iris' 将为每个物种年得出相同的答案。据我所知,“。”用于调用已经用 group_by 分组的数据。当我将您的代码应用于使用 nls 函数的实际问题时,出现错误。用“。”替换我的数据框产生在 OP 中进一步描述的错误。
  • 您的某些nls 调用似乎失败了,并且正在调用AIC 来自try 的错误消息。您可以尝试将 AIC(m.1) 替换为:ifelse(class(m.1) == "try-error", NA, AIC(m.1))。是的,你对这些点是正确的——在%&gt;% 之后,前面的东西被用作下一个函数的第一个参数。如果您想在其他地方使用它(即data = .),您需要使用一个点来表示这一点。还请查看broom + dplyr vignette - 它会帮助您顺利完成
猜你喜欢
  • 1970-01-01
  • 2015-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多