简体   繁体   中英

Create list of dataframes displaying AICc values from a nested list of models

I have a list of statistical models:

###Data import
Responses <- as.data.frame(matrix(sample(0:10, 1*100, replace=TRUE), ncol=2))
colnames(Responses) <- c("A","B")
Explanatories <- as.data.frame(matrix(sample(20:30, 1*100, replace=TRUE), ncol=2))
colnames(Explanatories) <- c("x","y")

###Create models
Models <- list(
lm(Responses$A ~ Explanatories$x),
lm(Responses$B ~ log10(Explanatories$x)),
lm(Responses$B ~ exp(Explanatories$y))
)

And a list of null models. These correspond to the models in the previous list, so for example I would want to compare the first lm in 'Models' against the first lm in 'Models_null':

Models_null <- list(
lm(Responses$A ~ 1),
lm(Responses$B ~ 1),
lm(Responses$B ~ 1)
)

All_models <- list(Models,Models_null)
names(All_models)<-c("full","res")

I would like to calculate an AICc score for each model using this formula:

aicc<-function(x) AIC(x)+((2*length(coef(x))*(length(coef(x))+1))/(length(resid(x))-length(coef(x))-1))

I need to do some calculations based on how AICc scores compare between each respective full and null model. So what I would need is a list of dataframes displaying the AICc scores for each pair of models, with 2 columns for 'full' and 'null . Thank you in advance for any help with this.

Here's a double sapply :

sapply(All_models, sapply, aicc)
#          full      res
# [1,] 267.4959 266.0534
# [2,] 251.9809 251.9127
# [3,] 253.5760 251.9127

The first sapply only goes over Models and Models_null . Then naturally for each of those two lists we again want to apply sapply , where for each model we will use aicc . That's precisely the @Rui Barradas' solution just in one line.

If needed, afterwards the result may be converted to a data frame, of course.


As to instead get a list whose elements are the rows of the above matrix, any of the following three will do:

lapply(seq_along(Models), function(i) 
  data.frame(full = aicc(Models[[i]]), null = aicc(Models_null[[i]])))

Map(data.frame, full = lapply(Models, aicc), null = lapply(Models_null, aicc))

do.call(Map, c(data.frame, lapply(All_models, sapply, aicc)))

This is just an application of *apply functions. I have chosen sapply because it returns a vector if possible.

Full <- sapply(Models, aicc)
Null <- sapply(Models_null, aicc)
df_aicc <- data.frame(Full, Null)

df_aicc
#      Full     Null
#1 269.7858 268.5274
#2 254.6533 253.0980
#3 254.8408 253.0980

In order to split this dataframe into a list of df's with one row per df use, well, split . By row name, which in R must be unique.

list_aicc <- split(df_aicc, row.names(df_aicc))
list_aicc
#$`1`
#      Full     Null
#1 269.7858 268.5274
#
#$`2`
#      Full    Null
#2 254.6533 253.098
#
#$`3`
#      Full    Null
#3 254.8408 253.098

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM