This post is for social science researchers and research psychologists who are doing factor analysis and want to create tables with fit measures in R. If you do not fit that very narrow audience you might not find this post interesting.
The Problem:
How to take the fit measures of multiple models and place them into a table (APA style) that can be put directly into a paper.
The solution:
First remove scientific notation from outputs (this is a personal preference of mine).
[code lang=”r”]options(scipen=999)[/code]
For Psyc package, note we have manually calculated the CFI in this piece of code because the psyc package does not have the CFI.
First compute the CFI (if you want that measure):
[code lang=”r”]CFImodel = 1 – ( ( model$STATISTIC – model$dof)/(model$null.chisq-model$null.dof ) )[/code]
Extract measures and save them to GoodnessfitMeasures variable.
[code lang=”r”]GoodnessfitMeasures = c(model$STATISTIC, model$PVAL,model$dof, CFImodel, model$TLI, model$RMSEA, model$rms)[/code]
Put into columns
[code lang=”r”]require(reshape)[/code]
[code lang=”r”]GoodnessfitMeasures = as.data.frame(GoodnessfitMeasures)[/code]
[code lang=”r”]GoodnessfitMeasures = melt(GoodnessfitMeasures, id.vars="GoodnessfitMeasures")
[/code]
Skip the next section if you are not using Lavaan and go to “Continued” below.
For Lavaan
[code lang=”r”]GoodnessfitMeasures = fitmeasures(fit, c("chisq", "df", "pvalue", "cfi", "tli", "rmsea", "rmsea.ci.lower", "rmsea.ci.upper", "srmr"))[/code]
Create names for colunms
[code lang=”r”]namess = c("Chisq", "DF", "P-Value", "CFI", "TLI", "RMSEA", "RMSEA ci upper", "RMSEA ci lower", "SRMR")[/code]
Put GoodnessfitMeasures into data frame (if you already did this for the psych package above no need to do it again).
[code lang=”r”]GoodnessfitMeasures = data.frame(GoodnessfitMeasures)[/code]
Continued
Use dplyr to bind names and fit measure. This will result in at least two columns. 1. the names of the fit measures Chisq, DF etc. 2. The corresponding fit measures (can have more than one column depending on how many models you have.
[code lang=”r”]all = bind_cols(namess, GoodnessfitMeasures)[/code]
There might be long numbers in each Create function to round all numbers of a data frame (function was found here: http://stackoverflow.com/questions/9063889/rounding-a-dataframe-in-r and works very well)
[code lang=”r”]round_df <- function(df, digits) {
nums <- vapply(df, is.numeric, FUN.VALUE = logical(1))
df[,nums] <- round(df[,nums], digits = digits)
(df)
}
[/code]
Round the numbers on the data frame
[code 1=”r” language=”lang”]GoodnessfitMeasures = round_df(all, digits=3)[/code]
Transpose the data frame so that the measures of each model take up a row rather than a column. This makes it easier to compare models if there are many of them. The result will be a matrix
[code lang=”r”]GoodnessfitMeasures = t(GoodnessfitMeasures)[/code]
I like to turn the matrix into a data frame
[code lang=”r”]GoodnessfitMeasures = as.data.frame(GoodnessfitMeasures)[/code]
Print the table as a latex then use suave to compile as a PDF. I personally then turn the PDF into a word doc using adobe pro. If you don’t have that there are other online options to turn PDFs into word docs.
[code lang=”r”] require(xtable)[/code]
[code lang=”r”] xtable(GoodnessfitMeasures)[/code]