R/model.summary.table.R

Defines functions model.summary.table

Documented in model.summary.table

#' Generate a Summary Table for a Linear Model
#'
#' This function creates a summary table for a linear model, including coefficients,
#' standard errors, p-values, and model statistics (e.g., MSE, R-squared). The table
#' is formatted for LaTeX output using the `kableExtra` package.
#'
#' @param model A linear model object (e.g., output from `lm()`).
#' @param caption A character string to be used as the caption for the table.
#'
#' @return A LaTeX-formatted table generated by `kableExtra::kable()`.
#'
#' @importFrom stats coef
#' @importFrom kableExtra kable row_spec column_spec footnote kable_styling
#' @export
#'
#' @examples
#' # Fit a linear model
#' model <- lm(mpg ~ wt + hp, data = mtcars)
#'
#' # Generate the summary table
#' model.summary.table(model, caption = "Linear Model Summary")
model.summary.table <- function(model, caption) {
  # Extract coefficient summary
  coef.summary <- summary(model)$coefficients
  model.summary <- summary(model)
  rounding.precision <- 5

  # Create coefficient table
  coef.table <- data.frame(
    Term = rownames(coef.summary),
    Estimate = round(coef.summary[, "Estimate"], rounding.precision),
    Std.Error = round(coef.summary[, "Std. Error"], rounding.precision),
    P.Value = round(coef.summary[, "Pr(>|t|)"], rounding.precision)
  )

  # Add significance codes
  coef.table$Signif. <- ifelse(coef.table$P.Value < 0.001, ":3",
                               ifelse(coef.table$P.Value < 0.01, ":)",
                                      ifelse(coef.table$P.Value < 0.05, ":/",
                                             ifelse(coef.table$P.Value < 0.1, "", ""))))

  # Calculate model statistics
  mse <- mean(model.summary$residuals^2)
  mse.adj <- mse * (length(model$fitted.values) / (length(model$fitted.values) - length(coef(model))))
  df <- model.summary$df[2]  # Residual degrees of freedom
  r.squared <- model.summary$r.squared
  adj.r.squared <- model.summary$adj.r.squared

  # Create model equation
  variable.names <- names(coef(model))[-1]  # Exclude intercept
  coefficients <- round(coef(model), 3)
  equation <- paste(model$terms[[2]], "=", coefficients[1])  # Start with intercept
  if (length(variable.names) > 10) {
    equation <- paste("too long :(")
  } else {
    for (i in seq_along(variable.names)) {
      equation <- paste(equation, " + ", coefficients[i + 1], "*", variable.names[i], sep = "")
    }
  }

  # Create model statistics table
  model.stats.table <- data.frame(
    Statistic = c("MSE", "MSE adj.", "df", "R-squared", "R-squared adj."),
    Value = c(round(mse, rounding.precision), round(mse.adj, rounding.precision), df, round(r.squared, rounding.precision), round(adj.r.squared, rounding.precision))
  )

  # Align rows between coefficient table and model statistics table
  if (nrow(coef.table) > nrow(model.stats.table)) {
    empty_rows <- data.frame(
      Statistic = rep("", nrow(coef.table) - nrow(model.stats.table)),
      Value = rep("", nrow(coef.table) - nrow(model.stats.table))
    )
    model.stats.table.aligned <- rbind(model.stats.table, empty_rows)
  } else {
    if (nrow(coef.table) < nrow(model.stats.table)) {
      diff <- nrow(model.stats.table) - nrow(coef.table)
      for (i in 1:diff) {
        coef.table[nrow(coef.table) + 1, ] <- data.frame(Term = "", Estimate = "", Std.Error = "", P.Value = "", Signif. = "")
      }
    }
    model.stats.table.aligned <- model.stats.table
  }

  # Combine tables
  final_table <- cbind(coef.table, model.stats.table.aligned)

  # Format and return LaTeX table
  final_table[, ] |>
    kableExtra::kable(format = "latex", caption = paste("\\textbf{", caption, "} \\newline \\textbf{", equation, "}"), digits = rounding.precision, row.names = FALSE) |>
    kableExtra::row_spec(0, bold = TRUE) |>
    kableExtra::column_spec(1, border_left = TRUE, border_right = FALSE, bold = TRUE) |>
    kableExtra::column_spec(6, border_left = TRUE, border_right = FALSE, bold = TRUE) |>
    kableExtra::column_spec(7, border_left = FALSE, border_right = TRUE) |>
    kableExtra::footnote(
      general = c("", "", "", "", "significance codes -  :3 -  >0.001 ", ":) - >0.01", ":/ - >0.05 ", ""),
      general_title = "",
      footnote_as_chunk = TRUE,
      threeparttable = TRUE
    ) |>
    kableExtra::kable_styling(latex_options = "HOLD_position")
}
#

Try the snazzieR package in your browser

Any scripts or data that you put into this service are public.

snazzieR documentation built on April 3, 2025, 5:58 p.m.