我有一个包含个人和年份观察的数据集。我想将数据隔离到每个人。在每个人中,我想每年适合一些模型。然后,我想将每个单年模型的AIC分数编译成data.frame
,然后将其保存在列表中。
我使用iris
数据创建了一个可重现的示例。我使用嵌套的for循环将数据子集化为个体(i),然后是年(j)。
问题:有些物种有三年的数据(例如setosa和versicolor),而virginica只有一年的数据(2014年)。
当物种data.frames
被添加到列表中时,少于三年的物种包含前几年的重复记录。如下面的结果所示,list[[3]]
应该包含2014年的弗吉尼亚种的单行数据,而不是2011年和2012年的杂色的重复记录。
是否可以列出具有不同行数的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"
答案 0 :(得分: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))