Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for analysis of deviance from car #580

Merged
merged 10 commits into from
Jul 2, 2024
5 changes: 4 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,16 @@ Suggests:
latex2exp,
lme4,
lmerTest,
MASS,
MBESS,
multcomp,
nlme,
nnet,
R.rsp,
skimr,
spelling,
testthat
testthat,
VGAM
SystemRequirements: Rendering the document template requires
pandoc (>= 2.0; https://pandoc.org) and for PDFs a TeX distribution,
such as TinyTeX (>= 0.12; https://yihui.org/tinytex/)
Expand Down
5 changes: 4 additions & 1 deletion R/add_custom_effect_sizes.R
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@

#' @keywords internal

add_custom_effect_sizes <- function(estimate, ...) {
UseMethod("add_custom_effect_sizes", estimate)
}

#' @keywords internal

add_custom_effect_sizes.character <- function(estimate, canonical_table, .x = NULL, ...) {

Expand All @@ -13,6 +14,7 @@ add_custom_effect_sizes.character <- function(estimate, canonical_table, .x = NU
add_effect_sizes(x = canonical_table, es = estimate, ...)
}

#' @keywords internal

add_custom_effect_sizes.data.frame <- function(estimate, canonical_table, intercept = FALSE, ...) {

Expand All @@ -32,6 +34,7 @@ add_custom_effect_sizes.data.frame <- function(estimate, canonical_table, interc
y
}

#' @keywords internal

add_custom_effect_sizes.function <- function(estimate, canonical_table, intercept = FALSE, .x = NULL, observed = NULL, ...) {

Expand Down
2 changes: 2 additions & 0 deletions R/apa_barplot.R
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ apa_barplot.default <- function(
, xlab = NULL
, ylab = NULL
, main = NULL
, set_par = TRUE
, ...
){
ellipsis <- defaults(
Expand All @@ -93,6 +94,7 @@ apa_barplot.default <- function(
, xlab = xlab
, ylab = ylab
, main = main
, set_par = set_par
, jit = .4 # add parameter 'space'
, plot = c("bars", "error_bars")
)
Expand Down
2 changes: 2 additions & 0 deletions R/apa_beeplot.R
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ apa_beeplot.default <- function(
, xlab = NULL
, ylab = NULL
, main = NULL
, set_par = TRUE
, ...
){
ellipsis <- defaults(
Expand All @@ -94,6 +95,7 @@ apa_beeplot.default <- function(
, xlab = xlab
, ylab = ylab
, main = main
, set_par = set_par
, plot = c("points", "error_bars", "swarms")
)
)
Expand Down
10 changes: 7 additions & 3 deletions R/apa_factorial_plot.R
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#' @param ylab Character or expression. Label for *y* axis.
#' @param main Character or expression. For up to two factors, simply specify the main title. If you stratify the data by more than two factors,
#' either specify a single value that will be added to automatically generated main title, *or* specify an array of multiple titles, one for each plot area.
#' @param set_par Logical. Determines whether `par(mfrow = .)` should be set for multi-panel plots.
#' @return A named (nested) list of plot options including raw and derived data. *Note that the structure of the return value is about to change in a forthcoming release of papaja.*
#' @inheritDotParams graphics::plot.window
#' @details
Expand Down Expand Up @@ -114,6 +115,7 @@ apa_factorial_plot.default <- function(
, xlab = NULL
, ylab = NULL
, main = NULL
, set_par = TRUE
, ...
){
# Data validation:
Expand Down Expand Up @@ -149,6 +151,8 @@ apa_factorial_plot.default <- function(
if(!is.null(ylab)) if(!is.expression(ylab)) validate(ylab, check_class = "character")
if(!is.null(main)) if(!is.expression(main)) if(!is.matrix(main)) validate(main, check_class = "character")

set_par <- isTRUE(set_par)

# remove extraneous columns from dataset
data <- data[, c(id, factors, dv)]

Expand Down Expand Up @@ -392,7 +396,7 @@ apa_factorial_plot.default <- function(
output$args <- do.call("apa_factorial_plot_single", ellipsis)
}

if(length(factors) > 2L) {
if(length(factors) > 2L && set_par) {
oldpar <- par(no.readonly = TRUE)
on.exit(par(oldpar))
}
Expand All @@ -401,7 +405,7 @@ apa_factorial_plot.default <- function(


if(length(factors) == 3) {
par(mfrow = c(1, nlevels(data[[factors[3]]])))
if(set_par) par(mfrow = c(1, nlevels(data[[factors[3]]])))
tmp_main <- ellipsis$main

# by default, only plot legend in topright plot:
Expand Down Expand Up @@ -457,7 +461,7 @@ apa_factorial_plot.default <- function(

## Four factors
if(length(factors)==4){
par(mfrow=c(nlevels(data[[factors[3]]]),nlevels(data[[factors[4]]])))
if(set_par) par(mfrow=c(nlevels(data[[factors[3]]]),nlevels(data[[factors[4]]])))
tmp_main <- ellipsis$main

legend.plot <- array(FALSE, dim=c(nlevels(data[[factors[3]]]), nlevels(data[[factors[4]]])))
Expand Down
2 changes: 2 additions & 0 deletions R/apa_lineplot.R
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ apa_lineplot.default <- function(
, xlab = NULL
, ylab = NULL
, main = NULL
, set_par = TRUE
, ...
){
ellipsis <- defaults(
Expand All @@ -97,6 +98,7 @@ apa_lineplot.default <- function(
, xlab = xlab
, ylab = ylab
, main = main
, set_par = set_par
, plot = c("points", "error_bars", "lines")
)
)
Expand Down
16 changes: 16 additions & 0 deletions R/apa_print_BFBayesFactor.R
Original file line number Diff line number Diff line change
Expand Up @@ -420,11 +420,16 @@ bf_sort_terms <- function(x) {

# }

#' @keywords internal

bf_add_estimates <- function(x, ...) UseMethod("bf_add_estimates", x@numerator[[1]])

#' @keywords internal

bf_add_estimates.default <- function(x, data_frame, ...) data_frame

#' @keywords internal

bf_add_estimates.BFoneSample <- function(
x
, data_frame
Expand Down Expand Up @@ -462,6 +467,7 @@ bf_add_estimates.BFoneSample <- function(
)
}

#' @keywords internal

bf_add_estimates.BFindepSample <- function(
x
Expand Down Expand Up @@ -495,6 +501,8 @@ bf_add_estimates.BFindepSample <- function(
)
}

#' @keywords internal

bf_add_estimates.BFcorrelation <- function(
x
, data_frame
Expand All @@ -510,6 +518,8 @@ bf_add_estimates.BFcorrelation <- function(
)
}

#' @keywords internal

bf_add_estimates.BFproportion <- function(
x
, data_frame
Expand All @@ -528,6 +538,7 @@ bf_add_estimates.BFproportion <- function(
)
}

#' @keywords internal

bf_sample_summarize <- function(
x
Expand Down Expand Up @@ -564,11 +575,16 @@ bf_sample_summarize <- function(
data_frame
}

#' @keywords internal

bf_add_names <- function(x, ...) UseMethod("bf_add_names", x@numerator[[1]])

#' @keywords internal

bf_add_names.default <- function(x, data_frame, ...) data_frame

#' @keywords internal

bf_add_names.BFlinearModel <- function(x, data_frame, ...) {
cbind(
model = names(x)$numerator
Expand Down
37 changes: 31 additions & 6 deletions R/apa_print_anova.R
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#' Typeset Statistical Results from ANOVA
#' Typeset Statistical Results from Analysis of Variance (or Deviance)
#'
#' These methods take objects from various R functions that calculate ANOVA to
#' create formatted character strings to report the results in accordance with
#' APA manuscript guidelines. For `anova`-objects from model comparisons see
#' \code{\link{apa_print.list}}.
#' These methods take objects from various R functions that calculate analysis
#' of variance (i.e., ANOVA) or analysis of deviance. They create formatted
#' character strings to report the results in accordance with APA manuscript
#' guidelines. For `anova`-objects from model comparisons see
#' [apa_print.list()].
#'
#' @param x An object containing the results from an analysis of variance ANOVA
#' @param correction Character. For repeated-measures ANOVA, the type of
Expand Down Expand Up @@ -415,6 +416,30 @@ apa_print.anova <- function(
, simplify = TRUE
)
)
# stats::anova.glm() and car::Anova.glm
} else if(any(grepl("Deviance", object_heading))) {
x$Term <-rownames(x)
y <- canonize(x)
y <- remove_residuals_row(y)
if(all(colnames(x) != "F values")) y$df.residual <- NULL
if(any(colnames(x) == "Cp")) y$df <- NULL

if(is.null(y$statistic)) {
y$statistic <- y$deviance
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, this I don't understand. Shouldn't canonize do this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would consider these fixes specific to analysis of deviance that do not fit into a generic function such as canonize() -- moving this to canonize() would imply that we would need a list of test statistics that should be reported with degrees of freedom and a list of test statistics that should not be reported with degrees of freedom.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand. This section does not deal with degrees of freedom, as far as I can tell. I'm referring here to the section where statistic is null and is replaced by deviance.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I accidentally deleted my last comment.

Maybe the most concise answer is the following: In one very specific case (chi-squared tests for generalized linear models), a column named Deviance contains the difference in deviance which is distributed as chi-squared, and is used as the test statistic.

In canonize(), however, we rename Deviance to deviance, not statistic, because columns of this name typically do not contain the test statistic, but simply the deviance of the model (in addition to the test statistic contained in another column). Because column Deviance containing the test statistic is the exception, not the rule, I would opt for sticking with the current behavior of canonize() and deal with the exception within the specific method.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What a mess. That makes sense, thanks for clarifying!

variable_label(y$statistic) <- "$\\chi^2$"
y$deviance <- NULL
}
y <- beautify(y, ...)
return(
glue_apa_results(
y
, est_glue = construct_glue(y, "estimate")
, stat_glue = construct_glue(y, "statistic")
, in_paren = in_paren
, simplify = TRUE
)
)

} else if(any(grepl("Satterthwaite|Kenward", object_heading))) {
# lmerTest::anova.merModLmerTest -------------------------------------------

Expand Down Expand Up @@ -481,7 +506,7 @@ apa_print.anova <- function(
} else if(identical(object_heading[1], "ANOVA-like table for random-effects: Single term deletions")) {
stop("Single-term deletions are not supported, yet.\nVisit https://github.com/crsh/papaja/issues to request support.")
}
# anova::lm (single model) ----
# anova.lm() (single model) ----
# Canonize, beautify, glue ----
y <- as.data.frame(x, stringsAsFactors = FALSE)
y$Effect <- trimws(rownames(y))
Expand Down
2 changes: 1 addition & 1 deletion R/apa_print_htest.R
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
#' large number of functions that produce these objects and their
#' idiosyncrasies, the returned strings should be compared to the original
#' object. If you experience inaccuracies you may report these
#' [here]{https://github.com/crsh/papaja/issues} (please include
#' [here](https://github.com/crsh/papaja/issues) (please include
#' a reproducible example in your report).
#'
#' `stat_name` and `est_name` are placed in the output string and are thus
Expand Down
7 changes: 7 additions & 0 deletions R/arrange_anova.R
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ arrange_anova <- function(x, ...) {
UseMethod("arrange_anova")
}

#' @keywords internal

arrange_anova.default <- function(x, ...) {
stop(paste0("Objects of class '", class(x), "' are currently not supported (no method defined).
Visit https://github.com/crsh/papaja/issues to request support for this class."))
Expand All @@ -43,6 +45,7 @@ arrange_anova.default <- function(x, ...) {

#' @rdname arrange_anova
#' @method arrange_anova anova
#' @keywords internal

arrange_anova.anova <- function(x, ...) {

Expand Down Expand Up @@ -83,6 +86,7 @@ arrange_anova.anova <- function(x, ...) {

#' @rdname arrange_anova
#' @method arrange_anova summary.aov
#' @keywords internal

arrange_anova.summary.aov <- function(x, ...) {

Expand Down Expand Up @@ -116,6 +120,8 @@ arrange_anova.summary.aov <- function(x, ...) {
variance_table
}

#' @keywords internal

arrange_anova.summary.aovlist <- function(x, ...) {
x <- lapply(x, arrange_anova.summary.aov)
variance_table <- do.call("rbind", x)
Expand All @@ -129,6 +135,7 @@ arrange_anova.summary.aovlist <- function(x, ...) {

#' @rdname arrange_anova
#' @method arrange_anova summary.Anova.mlm
#' @keywords internal

arrange_anova.summary.Anova.mlm <- function(x, correction = "GG", ...) {
validate(correction, check_class = "character", check_length = 1)
Expand Down
15 changes: 15 additions & 0 deletions R/lookup_tables.R
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ lookup_names <- c(
, "BIC" = "BIC"
, "npar" = "n.parameters"
, "alternative" = "alternative"
, "Deviance" = "deviance"
, "Resid..Dev" = "residual.deviance" # from broom
# term
, "Effect" = "term"
, "Term" = "term"
Expand Down Expand Up @@ -81,7 +83,9 @@ lookup_names <- c(
, "F.value" = "statistic"
, "F" = "statistic"
, "F.ratio" = "statistic"
, "F.values" = "statistic"
, "LRT" = "statistic"
, "LR.Chisq" = "statistic"
, "Chisq" = "statistic"
, "chisq" = "statistic"
, "X.squared" = "statistic"
Expand All @@ -99,6 +103,8 @@ lookup_names <- c(
, "logbf01" = "statistic"
, "Bartlett.s.K.2" = "statistic"
, "Bartlett.s.K.squared" = "statistic"
, "Rao" = "statistic"
, "Cp" = "statistic"
# df, df.residual
, "multivariate.df1" = "multivariate.df"
, "multivariate.df2" = "multivariate.df.residual"
Expand All @@ -121,9 +127,11 @@ lookup_names <- c(
, "denom.df" = "df.residual"
, "den.df" = "df.residual"
, "Res.Df" = "df.residual"
, "Resid..Df" = "df.residual"
# p.value
, "p.value" = "p.value"
, "Pr..Chisq." = "p.value"
, "Pr..Chi." = "p.value"
, "Pr..F." = "p.value"
, "Pr..PB." = "p.value"
, "Pr...t.." = "p.value"
Expand All @@ -148,6 +156,8 @@ lookup_labels <- c(
, "BIC" = "$\\mathit{BIC}$"
, "npar" = "$k$"
, "alternative" = "$\\mathcal{H}_1$"
, "Deviance" = "$\\mathit{Dev}$"
, "Resid..Dev" = "$\\mathit{Dev}_{\\mathrm{res}}$"
# term
, "Effect" = "Effect"
, "Term" = "Term"
Expand Down Expand Up @@ -199,8 +209,10 @@ lookup_labels <- c(
, "F.value" = "$F$"
, "F" = "$F$"
, "F.ratio" = "$F$"
, "F.values" = "$F$"
, "approx.F" = "$F$"
, "LRT" = "$\\chi^2$"
, "LR.Chisq" = "$\\chi^2$"
, "chisq" = "$\\chi^2$"
, "Chisq" = "$\\chi^2$"
, "X.squared" = "$\\chi^2$"
Expand All @@ -218,6 +230,8 @@ lookup_labels <- c(
, "logbf01" = "$\\log \\mathrm{BF}_{\\textrm{01}}$"
, "Bartlett.s.K.2" = "$K^2$"
, "Bartlett.s.K.squared" = "$K^2$"
, "Rao" = "$\\mathit{RS}$"
, "Cp" = "$C_p$"
# df, df.residual
, "multivariate.df" = "$\\mathit{df}$"
, "multivariate.df.residual" = "$\\mathit{df}_{\\mathrm{res}}$"
Expand Down Expand Up @@ -246,6 +260,7 @@ lookup_labels <- c(
, "Pr...z.." = "$p$"
, "pvalues" = "$p$"
, "Pr..Chisq." = "$p$"
, "Pr..Chi." = "$p$"
, "Pr..F." = "$p$"
, "Pr..PB." = "$p$"
, "adj.p.value" = "$p_\\mathrm{adj}$"
Expand Down
Loading
Loading