R/summary.R

Defines functions print.summary.psem summary.psem

Documented in print.summary.psem summary.psem

#' Summarizing piecewise structural equation models
#'
#' Returns information necessary to interpret piecewise structural equation
#' models, including tests of directed separation, path coefficients,
#' information criterion values, and R-squared values of individual models.
#'
#' The forthcoming argument \code{groups} splits the analysis based on an optional grouping
#' factor, conducts separate d-sep tests, and reports goodness-of-fit and path
#' coefficients for each submodel. The procedure is approximately similar to a
#' multigroup analysis in traditional variance-covariance SEM. Coming in version 2.1.
#'
#' In cases involving non-normally distributed responses in the independence
#' claims that are modeled using generalized linear models, the significance of
#' the independence claim is not reversible (e.g., the P-value of Y ~ X is not
#' the same as X ~ Y). This is due to the transformation of the response via
#' the link function. In extreme cases, this can bias the goodness-of-fit
#' tests. \code{summary.psem} will issue a warning when this case is present
#' and provide guidance for solutions. One solution is to specify the
#' directionality of the relationship using the \code{direction} argument, e.g.
#' \code{direction = c("X <- Y")}. Another is to run both tests (Y ~ X, X ~ Y)
#' and return the most conservative (i.e., lowest) P-value, which can be
#' toggled using the \code{conserve = TRUE} argument.
#'
#' In some cases, additional claims that were excluded from the basis set can
#' be added back in using the argument \code{add.claims}. These could be, for
#' instance, independence claims among exogenous variables. See Details in
#' \code{\link{basisSet}}.
#'
#' Standardized path coefficients are scaled by standard deviations.
#'
#' @param object a list of structural equations
#' @param ... additional arguments to summary
#' @param basis.set an optional basis set
#' @param direction a vector of claims defining the specific directionality of any independence 
#' claim(s)
#' @param interactions whether interactions should be included in independence claims. 
#' Default is FALSE
#' @param conserve whether the most conservative P-value should be returned (See Details) 
#' Default is FALSE
#' @param conditioning whether all conditioning variables should be shown in the table
#' Default is FALSE
#' @param add.claims an optional vector of additional independence claims (P-values) 
#' to be added to the basis set
#' @param intercepts whether intercepts should be included in the coefficient  table
#' Default is FALSE
#' @param standardize whether standardized path coefficients should be reported 
#' Default is "scale"
#' @param standardize.type the type of standardized for non-Gaussian responses: 
#' \code{latent.linear} (default), \code{Mendard.OE}
#' @param test.statistic the type of test statistic generated by \code{\link{Anova}}
#' @param test.type the type of test ("II" or "III") for significance of categorical
#' variables (from \code{car::Anova})
#' @param AIC.type whether the log-likelihood \code{"loglik"} or d-sep \code{"dsep"} AIC score 
#' should be reported. Default is \code{"loglik"}
#' @param .progressBar an optional progress bar. Default is TRUE
#' 
#' @return The function \code{summary.psem} returns a list of summary
#' statistics: \item{dTable}{ A summary table of the tests of directed
#' separation, from \code{\link{dSep}}.  } \item{CStat}{ Fisher's C statistic,
#' degrees of freedom, and significance value based on a Chi-square test.  }
#' \item{AIC}{ Information criterion (Akaike, corrected Akaike) as
#' well as degrees of freedom and sample size.  } \item{coefficients}{ A
#' summary table of the path coefficients, from \code{link{coefs}}.  }
#' \item{R2}{ (Pseudo)-R2 values, from \code{\link{rsquared}}.  }
#' 
#' @author Jon Lefcheck <lefcheckj@@si.edu>
#' 
#' @seealso The model fitting function \code{\link{psem}}.
#' 
#' @references Shipley, Bill. "A new inferential test for path models based on
#' directed acyclic graphs." Structural Equation Modeling 7.2 (2000): 206-218.
#'
#' Shipley, Bill. Cause and correlation in biology: a user's guide to path
#' analysis, structural equations and causal inference. Cambridge University
#' Press, 2002.
#'
#' Shipley, Bill. "Confirmatory path analysis in a generalized multilevel
#' context." Ecology 90.2 (2009): 363-368.
#'
#' Shipley, Bill. "The AIC model selection method applied to path analytic
#' models compared using a d-separation test." Ecology 94.3 (2013): 560-564.
#' 
#' @method summary psem
#'
#' @export
#' 
summary.psem <- function(object, ...,
                         basis.set = NULL, direction = NULL, interactions = FALSE, conserve = FALSE, conditioning = FALSE,
                         add.claims = NULL,
                         standardize = "scale", standardize.type = "latent.linear", 
                         test.statistic = "F", test.type = "II",
                         intercepts = FALSE,
                         AIC.type = "loglik",
                         .progressBar = TRUE) {

  name <- deparse(match.call()$object)

  call <- paste(listFormula(object), collapse = "\n  ")

  dTable <- dSep(object, basis.set, direction, interactions, conserve, conditioning, .progressBar)

  Cstat <- fisherC(dTable, add.claims, direction, interactions, conserve, conditioning, .progressBar)

  ChiSq <- LLchisq(object, basis.set, direction, interactions, conserve)
  
  AIC <- AIC_psem(object, AIC.type, add.claims, direction, interactions, conserve, conditioning, .progressBar)

  coefficients <- coefs(object, standardize, standardize.type, test.statistic, test.type, intercepts)

  R2 <- rsquared(object)

  R2[, which(sapply(R2, is.numeric))] <- round(R2[, which(sapply(R2, is.numeric))], 2)

  if(length(dTable) > 0)

    dTable[, which(sapply(dTable, is.numeric))] <- round(dTable[, which(sapply(dTable, is.numeric))], 4)

  l <- list(name = name, call = call, dTable = dTable, ChiSq = ChiSq, Cstat = Cstat, 
            AIC = AIC, coefficients = coefficients, R2 = R2)

  class(l) <- "summary.psem"

  l

} 

#' Print summary
#' 
#' @param x an object of class summary.psem
#' @param ... further arguments passed to or from other methods
#' 
#' @method print summary.psem
#' 
#' @export
#' 
print.summary.psem <- function(x, ...) {

  cat("\nStructural Equation Model of", as.character(x$name), "\n")

  cat("\nCall:\n ", x$call)

  cat("\n")

  cat("\n    AIC")
  cat("\n", as.character(sprintf("%.3f", x$AIC[1])))

  cat("\n")

  cat("\n---\nTests of directed separation:\n\n", captureTable(x$dTable))

  cat("\n--\nGlobal goodness-of-fit:\n\nChi-Squared =", as.character(x$ChiSq[1]),
      "with P-value =", as.character(x$ChiSq[3]),
      "and on", as.character(x$ChiSq)[2], "degrees of freedom")
  
  cat("\nFisher's C =", as.character(x$Cstat[1]),
      "with P-value =", as.character(x$Cstat[3]),
      "and on", as.character(x$Cstat[2]), "degrees of freedom")

  cat("\n\n---\nCoefficients:\n\n", captureTable(x$coefficients))

  cat("\n  Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05")

  cat("\n\n---\nIndividual R-squared:\n\n", captureTable(x$R2[, c(1, 4:ncol(x$R2))]))

  invisible(x)

}
jslefche/piecewiseSEM documentation built on June 5, 2023, 6:19 a.m.