diff --git a/DESCRIPTION b/DESCRIPTION index 070583b..1422c47 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,8 +1,8 @@ Package: ggpmisc Type: Package Title: Miscellaneous Extensions to 'ggplot2' -Version: 0.5.6 -Date: 2024-05-07 +Version: 0.5.6.9001 +Date: 2024-05-13 Authors@R: c( person("Pedro J.", "Aphalo", email = "pedro.aphalo@helsinki.fi", role = c("aut", "cre"), comment = c(ORCID = "0000-0003-3385-972X")), diff --git a/NAMESPACE b/NAMESPACE index 1ec0ac3..e1e737e 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,6 +1,5 @@ # Generated by roxygen2: do not edit by hand -S3method(as.character,polynomial) S3method(coef,lmodel2) S3method(confint,lmodel2) S3method(predict,lmodel2) @@ -25,11 +24,23 @@ export(StatQuantBand) export(StatQuantEq) export(StatQuantLine) export(StatValleys) +export(adj_rr_label) +export(bold_label) +export(coefs2poly_eq) +export(f_value_label) export(find_peaks) +export(italic_label) export(keep_augment) export(keep_glance) export(keep_tidy) export(outcome2factor) +export(p_value_label) +export(plain_label) +export(poly2character) +export(r_ci_label) +export(r_label) +export(rr_ci_label) +export(rr_label) export(scale_color_logFC) export(scale_color_outcome) export(scale_colour_logFC) @@ -43,6 +54,7 @@ export(scale_x_logFC) export(scale_y_FDR) export(scale_y_Pvalue) export(scale_y_logFC) +export(sprintf_dm) export(stat_correlation) export(stat_fit_augment) export(stat_fit_deviations) @@ -62,8 +74,10 @@ export(stat_quant_eq) export(stat_quant_line) export(stat_valleys) export(symmetric_limits) +export(t_value_label) export(threshold2factor) export(use_label) +export(value2char) export(xy_outcomes2factor) export(xy_thresholds2factor) import(ggpp) diff --git a/NEWS.md b/NEWS.md index f4428d6..c99deb1 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,6 +4,13 @@ editor_options: wrap: 72 --- +# ggpmisc 0.6.0 + +- Support decreasing-power order of polynomial terms in `stat_poly_eq()`, `stat_quant_eq()` and `stat_ma_eq()`. +- Return new `qtl.label` for quantiles, separately from `grp.label`, which now works as in the other statistics based on a pseudo aesthetic. **This is a code breaking change affecting some plots.** +- Small visual changes in the formatting labels also affect some plots as the default number of digits was increased in a few cases. New utility functions used in `stat_poly_eq()`, `stat_ma_eq()`, `stat_quant_eq()`, `stat_correlation()`, and `stat_multcomp()`. +- Export new utility functions used for formatting parameter estimates into character strings. + # ggpmisc 0.5.6 - Rename parameter `trans` of `scale_y_Pvalue()` into `transform` to track deprecation in 'ggplot2' 3.5.0. diff --git a/R/stat-correlation.R b/R/stat-correlation.R index 7de6612..53ab15c 100644 --- a/R/stat-correlation.R +++ b/R/stat-correlation.R @@ -368,6 +368,7 @@ cor_test_compute_fun <- function(data, output.type, boot.R, na.rm) { + # Much of the complexity of the label formatting is needed to # prevent the automatic dropping of trailing zeros in expressions. # The approach used is to include formatted numbers as character @@ -454,6 +455,8 @@ cor_test_compute_fun <- function(data, estimate = "rho", alternative = "test")) + # assign values common to all output types + z <- htest.ls[names(idx.map[[method]])] names(z) <- unname(idx.map[[method]]) @@ -489,297 +492,69 @@ cor_test_compute_fun <- function(data, if (output.type == "numeric") { z[["r.label"]] <- NA_character_ } else { - # warn if too narrow formats requested - stopifnot("'r.digits' must be > 0" = r.digits > 0) - if (r.digits < 2) { - warning("'r.digits < 2' Likely information loss!") - } - stopifnot("'t.digits' must be > 0" = t.digits > 0) - if (t.digits < 2) { - warning("'t.digits < 2' Likely information loss!") - } - stopifnot("'p.digits' must be > 0" = p.digits > 0) - if (p.digits < 2) { - warning("'p.digits < 2' Likely information loss!") - } - # build the character strings - if (output.type == "expression") { - if (p.digits == Inf) { - p.value.char <- sprintf_dm("%#.2e", z[["p.value"]], decimal.mark = decimal.mark) - p.value.char <- paste(gsub("e", " %*% 10^{", p.value.char), "}", sep = "") - } else { - p.value.char <- sprintf_dm("\"%#.*f\"", p.digits, z[["p.value"]], decimal.mark = decimal.mark) - } - r <- z[[unname(c(pearson = "cor", kendall = "tau", spearman = "rho")[method])]] - r.char <- sprintf_dm("\"%#.*f\"", r.digits, r, decimal.mark = decimal.mark) - r.confint.chr <- paste(sprintf_dm("%#.*f", - r.digits, z[["r.confint.low"]], decimal.mark = decimal.mark), - sprintf_dm("%#.*f", - r.digits, z[["r.confint.high"]], decimal.mark = decimal.mark), - sep = range.sep) - if (as.logical((z[["r.conf.level"]] * 100) %% 1)) { - conf.level.digits = 1L - } else { - conf.level.digits = 0L - } - conf.level.chr <- sprintf_dm("%.*f", conf.level.digits, z[["r.conf.level"]] * 100, decimal.mark = decimal.mark) - if (method == "pearson") { - rr.char <- sprintf_dm("\"%#.*f\"", r.digits, r^2, decimal.mark = decimal.mark) - t.value.char <- sprintf_dm("\"%#.*g\"", t.digits, z[["t.value"]], decimal.mark = decimal.mark) - if (grepl("e", t.value.char)) { - t.value.char <- sprintf_dm("%#.*e", t.digits, z[["t.value"]], decimal.mark = decimal.mark) - t.value.char <- paste(gsub("e", " %*% 10^{", t.value.char), "}", sep = "") - } - df.char <- as.character(z[["df"]]) - } else if (method == "kendall") { - z.value.char <- sprintf_dm("\"%#.*g\"", t.digits, z[["z.value"]], decimal.mark = decimal.mark) - if (grepl("e", z.value.char)) { - z.value.char <- sprintf_dm("%#.*e", t.digits, z[["z.value"]], decimal.mark = decimal.mark) - z.value.char <- paste(gsub("e", " %*% 10^{", z.value.char), "}", sep = "") - } - } else if (method == "spearman") { - S.value.char <- sprintf_dm("\"%#.*g\"", t.digits, z[["S.value"]], decimal.mark = decimal.mark) - if (grepl("e", S.value.char)) { - S.value.char <- sprintf_dm("%#.*e", t.digits, z[["S.value"]], decimal.mark = decimal.mark) - S.value.char <- paste(gsub("e", " %*% 10^{", S.value.char), "}", sep = "") - } - } - } else { - if (p.digits == Inf) { - p.value.char <- sprintf_dm("%#.2e", z[["p.value"]], decimal.mark = decimal.mark) - } else { - p.value.char <- sprintf_dm("%#.*f", p.digits, z[["p.value"]], decimal.mark = decimal.mark) - } - r <- z[[unname(c(pearson = "cor", kendall = "tau", spearman = "rho")[method])]] - r.char <- sprintf_dm("%#.*f", r.digits, r, decimal.mark = decimal.mark) - r.confint.chr <- paste(sprintf_dm("%#.*f", - r.digits, z[["conf.int.low"]], decimal.mark = decimal.mark), - sprintf_dm("%#.*f", - r.digits, z[["conf.int.high"]], decimal.mark = decimal.mark), - sep = range.sep) - if (as.logical((z[["r.conf.level"]] * 100) %% 1)) { - conf.level.digits = 1L - } else { - conf.level.digits = 0L - } - conf.level.chr <- sprintf_dm("%.*f", conf.level.digits, z[["r.conf.level"]] * 100, decimal.mark = decimal.mark) - if (method == "pearson") { - rr.char <- sprintf_dm("\"%#.*f\"", r.digits, r^2, decimal.mark = decimal.mark) - t.value.char <- sprintf_dm("%#.*g", t.digits, z[["t.value"]], decimal.mark = decimal.mark) - df.char <- as.character(z[["df"]]) - } else if (method == "kendall") { - z.value.char <- sprintf_dm("%#.*g", t.digits, z[["z.value"]], decimal.mark = decimal.mark) - } else if (method == "spearman") { - S.value.char <- sprintf_dm("%#.*g", t.digits, z[["S.value"]], decimal.mark = decimal.mark) - } - } + r <- z[[unname(c(pearson = "cor", kendall = "tau", spearman = "rho")[method])]] - # add labels to data.frame z.labels - if (output.type == "expression") { - # character(0) instead of "" avoids in paste() the insertion of sep for missing labels - z[["p.value.label"]] <- - ifelse(is.na(z[["p.value"]]), character(0L), - paste(ifelse(small.p, "italic(p)", "italic(P)"), - ifelse(z[["p.value"]] < 10^(-p.digits), - sprintf_dm("\"%.*f\"", p.digits, 10^(-p.digits), decimal.mark = decimal.mark), - p.value.char), - sep = ifelse(z[["p.value"]] < 10^(-p.digits), - "~`<`~", - "~`=`~"))) - z[["n.label"]] <- - paste("italic(n)~`=`~\"", z[["n"]], "\"", sep = "") - z[["grp.label"]] <- grp.label - if (method == "pearson") { - z[["cor.label"]] <- z[["r.label"]] <- - ifelse(is.na(z[["cor"]]), character(0L), - paste(ifelse(small.r, "italic(r)", "italic(R)"), - ifelse(abs(z[["cor"]]) < 10^(-r.digits), - sprintf_dm("\"%.*f\"", r.digits, 10^(-r.digits) * sign(z[["cor"]]), decimal.mark = decimal.mark), - r.char), - sep = ifelse(abs(z[["cor"]]) < 10^(-r.digits), - c("~`>`~", "~`=`~", "~`<`~")[sign(z[["cor"]]) + 2], - "~`=`~"))) - z[["rr.label"]] <- - paste(ifelse(small.r, "italic(r)^2", "italic(R)^2"), - ifelse(r^2 < 10^(-r.digits) & r^2 != 0, - sprintf_dm("\"%.*f\"", r.digits, 10^(-r.digits), decimal.mark = decimal.mark), - rr.char), - sep = ifelse(r^2 < 10^(-r.digits) & r^2 != 0, - "~`<`~", - "~`=`~")) - z[["t.value.label"]] <- - ifelse(is.na(z[["t.value"]]), character(0L), - paste("italic(t)[", df.char, "]~`=`~", t.value.char, sep = "")) - z[["r.confint.label"]] <- z[["cor.confint.label"]] <- - paste("\"", conf.level.chr, "% CI ", CI.brackets[1], r.confint.chr, CI.brackets[2], "\"", sep = "") - } else if (method == "kendall") { - z[["tau.label"]] <- z[["r.label"]] <- - ifelse(is.na(z[["tau"]]), character(0L), - paste("italic(tau)", - ifelse(abs(z[["tau"]]) < 10^(-r.digits), - sprintf_dm("\"%.*f\"", r.digits, 10^(-r.digits) * sign(z[["tau"]]), decimal.mark = decimal.mark), - r.char), - sep = ifelse(abs(z[["tau"]]) < 10^(-r.digits), - c("~`>`~", "~`=`~", "~`<`~")[sign(z[["tau"]]) + 2], - "~`=`~"))) - z[["z.value.label"]] <- - ifelse(is.na(z[["z.value"]]), character(0L), - paste("italic(z)~`=`~", z.value.char, sep = "")) - z[["r.confint.label"]] <- z[["tau.confint.label"]] <- - paste("\"", conf.level.chr, "% CI ", CI.brackets[1], r.confint.chr, CI.brackets[2], "\"", sep = "") - } else if (method == "spearman") { - z[["rho.label"]] <- z[["r.label"]] <- - ifelse(is.na(z[["rho"]]), character(0L), - paste("italic(rho)", - ifelse(abs(z[["rho"]]) < 10^(-r.digits), - sprintf_dm("\"%.*f\"", r.digits, 10^(-r.digits) * sign(z[["rho"]]), decimal.mark = decimal.mark), - r.char), - sep = ifelse(abs(z[["rho"]]) < 10^(-r.digits), - c("~`>`~", "~`=`~", "~`<`~")[sign(z[["rho"]]) + 2], - "~`=`~"))) - z[["S.value.label"]] <- - ifelse(is.na(z[["S.value"]]), character(0L), - paste("italic(S)~`=`~", S.value.char, sep = "")) - z[["r.confint.label"]] <- z[["rho.confint.label"]] <- - paste("\"", conf.level.chr, "% CI ", CI.brackets[1], r.confint.chr, CI.brackets[2], "\"", sep = "") - } - z[["method.label"]] <- - paste("\"method: ", method, "\"", sep = "") - } else if (output.type %in% c("latex", "tex", "text", "tikz")) { - z[["p.value.label"]] <- - ifelse(is.na(z[["p.value"]]), character(0L), - paste(ifelse(small.p, "p", "P"), - ifelse(z[["p.value"]] < 10^(-p.digits), - sprintf_dm("\"%.*f\"", p.digits, 10^(-p.digits), decimal.mark = decimal.mark), - p.value.char), - sep = ifelse(z[["p.value"]] < 10^(-p.digits), - " < ", - " = "))) - z[["n.label"]] <- - paste("n = ", z[["n"]], sep = "") - z[["grp.label"]] <- grp.label - if (method == "pearson") { - z[["cor.label"]] <- z[["r.label"]] <- - ifelse(is.na(z[["cor"]]), character(0L), - paste(ifelse(small.r, "r", "R"), - ifelse(abs(z[["cor"]]) < 10^(-r.digits), - sprintf_dm("\"%.*f\"", r.digits, 10^(-r.digits) * sign(z[["cor"]]), decimal.mark = decimal.mark), - r.char), - sep = ifelse(abs(z[["cor"]]) < 10^(-r.digits), - c(" > ", " = ", " < ")[sign(z[["cor"]]) + 2], - " = "))) - z[["rr.label"]] <- - paste(ifelse(small.r, "italic(r)^2", "italic(R)^2"), - ifelse(r^2 < 10^(-r.digits) & r^2 != 0, - sprintf_dm("\"%.*f\"", r.digits, 10^(-r.digits), decimal.mark = decimal.mark), - rr.char), - sep = ifelse(r^2 < 10^(-r.digits) & r^2 != 0, - "~`<`~", - "~`=`~")) - z[["t.value.label"]] <- ifelse(is.na(z[["t.value"]]), character(0L), - paste("t_{", df.char, "} = ", t.value.char, sep = "")) - z[["r.confint.label"]] <- z[["cor.confint.label"]] <- - paste(conf.level.chr, "% CI ", CI.brackets[1], r.confint.chr, CI.brackets[2], sep = "") - } else if (method == "kendall") { - z[["tau.label"]] <- z[["r.label"]] <- - ifelse(is.na(z[["tau"]]), character(0L), - paste(ifelse(output.type == "text", - "tau", "\tau"), - ifelse(abs(z[["tau"]]) < 10^(-r.digits), - sprintf_dm("\"%.*f\"", r.digits, 10^(-r.digits) * sign(z[["tau"]]), decimal.mark = decimal.mark), - r.char), - sep = ifelse(abs(z[["tau"]]) < 10^(-r.digits), - c(" > ", " = ", " < ")[sign(z[["tau"]]) + 2], - " = "))) - z[["z.value.label"]] <- ifelse(is.na(z[["z.value"]]), character(0L), - paste("z = ", z.value.char, sep = "")) - z[["r.confint.label"]] <- z[["tau.confint.label"]] <- - paste(conf.level.chr, "% CI ", CI.brackets[1], r.confint.chr, CI.brackets[2], sep = "") - } else if (method == "spearman") { - z[["rho.label"]] <- z[["r.label"]] <- - ifelse(is.na(z[["rho"]]), character(0L), - paste(ifelse(output.type == "text", - "rho", "\rho"), - ifelse(abs(z[["rho"]]) < 10^(-r.digits), - sprintf_dm("\"%.*f\"", r.digits, 10^(-r.digits) * sign(z[["rho"]]), decimal.mark = decimal.mark), - r.char), - sep = ifelse(abs(z[["rho"]]) < 10^(-r.digits), - c(" > ", " = ", " < ")[sign(z[["rho"]]) + 2], - " = "))) - z[["S.value.label"]] <- ifelse(is.na(z[["S.value"]]), character(0L), - paste("S = ", S.value.char, sep = "")) - z[["r.confint.label"]] <- z[["rho.confint.label"]] <- - paste(conf.level.chr, "% CI ", CI.brackets[1], r.confint.chr, CI.brackets[2], sep = "") - } - z[["method.label"]] <- paste("method: ", method, sep = "") - } else if (output.type == "markdown") { - z[["p.value.label"]] <- - ifelse(is.na(z[["p.value"]]), character(0L), - paste(ifelse(small.p, "_p_", "_P_"), - ifelse(z[["p.value"]] < 10^(-p.digits), - sprintf_dm("\"%.*f\"", p.digits, 10^(-p.digits), decimal.mark = decimal.mark), - p.value.char), - sep = ifelse(z[["p.value"]] < 10^(-p.digits), - " < ", - " = "))) - z[["n.label"]] <- - paste("_n_ = ", z[["n"]], sep = "") - z[["grp.label"]] <- grp.label - if (method == "pearson") { - z[["cor.label"]] <- z[["r.label"]] <- - ifelse(is.na(z[["cor"]]), character(0L), - paste(ifelse(small.r, "_r_", "_R_"), - ifelse(abs(z[["cor"]]) < 10^(-r.digits), - sprintf_dm("\"%.*f\"", r.digits, 10^(-r.digits) * sign(z[["cor"]]), decimal.mark = decimal.mark), - r.char), - sep = ifelse(abs(z[["cor"]]) < 10^(-r.digits), - c(" > ", " = ", " < ")[sign(z[["cor"]]) + 2], - " = "))) - z[["rr.label"]] <- - paste(ifelse(small.r, "_r_2", "_R_2"), - ifelse(r^2 < 10^(-r.digits) & r^2 != 0, - sprintf_dm("\"%.*f\"", r.digits, 10^(-r.digits), decimal.mark = decimal.mark), - rr.char), - sep = ifelse(r^2 < 10^(-r.digits) & r^2 != 0, - " < ", - " = ")) - z[["t.value.label"]] <- ifelse(is.na(z[["t.value"]]), character(0L), - paste("_t_", df.char, " = ", t.value.char, sep = "")) - z[["r.confint.label"]] <- z[["cor.confint.label"]] <- - paste(conf.level.chr, "% CI ", CI.brackets[1], r.confint.chr, CI.brackets[1], sep = "") - } else if (method == "kendall") { - z[["tau.label"]] <- z[["r.label"]] <- - ifelse(is.na(z[["tau"]]), character(0L), - paste("_τ_", - ifelse(abs(z[["tau"]]) < 10^(-r.digits), - sprintf_dm("\"%.*f\"", r.digits, 10^(-r.digits) * sign(z[["tau"]]), decimal.mark = decimal.mark), - r.char), - sep = ifelse(abs(z[["tau"]]) < 10^(-r.digits), - c(" > ", " = ", " < ")[sign(z[["tau"]]) + 2], - " = "))) - z[["z.value.label"]] <- ifelse(is.na(z[["t.value"]]), character(0L), - paste("_z_ = ", z.value.char, sep = "")) - z[["r.confint.label"]] <- z[["tau.confint.label"]] <- - paste(conf.level.chr, "% CI ", CI.brackets[1], r.confint.chr, CI.brackets[2], sep = "") - } else if (method == "spearman") { - z[["rho.label"]] <- z[["r.label"]] <- - ifelse(is.na(z[["rho"]]), character(0L), - paste("_ρ_", - ifelse(abs(z[["rho"]]) < 10^(-r.digits), - sprintf_dm("\"%.*f\"", r.digits, 10^(-r.digits) * sign(z[["rho"]]), decimal.mark = decimal.mark), - r.char), - sep = ifelse(abs(z[["rho"]]) < 10^(-r.digits), - c(" > ", " = ", " < ")[sign(z[["rho"]]) + 2], - " = "))) - z[["S.value.label"]] <- ifelse(is.na(z[["S.value"]]), character(0L), - paste("_S_ = ", S.value.char, sep = "")) - z[["r.confint.label"]] <- z[["rho.confint.label"]] <- - paste(conf.level.chr, "% CI ", CI.brackets[1], r.confint.chr, CI.brackets[2], sep = "") - } - z[["method.label"]] <- paste("method: ", method, sep = "") - } else { - warning("Unknown 'output.type' argument: ", output.type) + z[["p.value.label"]] <- p_value_label(value = z[["p.value"]], + small.p = small.p, + digits = p.digits, + fixed = TRUE, + output.type = output.type, + decimal.mark = decimal.mark) + z[["n.label"]] <- italic_label(value = z[["n"]], + value.name = "n", + digits = 0, + output.type = output.type, + decimal.mark = decimal.mark) + z[["grp.label"]] <- grp.label + z[["r.label"]] <- r_label(value = r, + method = method, + small.r = small.r, + digits = r.digits, + fixed = TRUE, + output.type = output.type, + decimal.mark = decimal.mark) + z[["r.confint.label"]] <- r_ci_label(value = c(z[["r.confint.low"]], + z[["r.confint.high"]]), + conf.level = z[["r.conf.level"]], + range.brackets = CI.brackets, + range.sep = NULL, + digits = r.digits, + output.type = output.type, + decimal.mark = decimal.mark) + z[["method.label"]] <- paste("\"method: ", method, "\"", sep = "") + if (method == "pearson") { + z[["cor.label"]] <- z[["r.label"]] + z[["rr.label"]] <- rr_label(value = z[["cor"]]^2, + small.r = small.r, + digits = r.digits, + fixed = TRUE, + output.type = output.type, + decimal.mark = decimal.mark) + z[["t.value.label"]] <- t_value_label(value = z[["t.value"]], + df = z[["df"]], + digits = t.digits, + fixed = FALSE, + output.type = output.type, + decimal.mark = decimal.mark) + } else if (method == "kendall") { + z[["tau.label"]] <- z[["r.label"]] + z[["tau.confint.label"]] <- z[["r.confint.label"]] + z[["z.value.label"]] <- italic_label(value = z[["z.value"]], + value.name = "z", + digits = t.digits, + fixed = FALSE, + output.type = output.type, + decimal.mark = decimal.mark) + } else if (method == "spearman") { + z[["rho.label"]] <- z[["r.label"]] + z[["rho.confint.label"]] <- z[["r.confint.label"]] + z[["S.value.label"]] <- italic_label(value = z[["S.value"]], + value.name = "S", + digits = t.digits, + fixed = FALSE, + output.type = output.type, + decimal.mark = decimal.mark) } } diff --git a/R/stat-ma-eq.R b/R/stat-ma-eq.R index 31a8bb4..b2bc4c7 100644 --- a/R/stat-ma-eq.R +++ b/R/stat-ma-eq.R @@ -50,6 +50,8 @@ #' the fitted coefficients. #' @param coef.keep.zeros logical Keep or drop trailing zeros when formatting #' the fitted coefficients and F-value. +#' @param decreasing logical It specifies the order of the terms in the +#' returned character string; in increasing (default) or decreasing powers. #' @param rr.digits,theta.digits,p.digits integer Number of digits after the #' decimal point to use for R^2, theta and P-value in labels. If \code{Inf}, #' use exponential notation with three decimal places. @@ -115,6 +117,15 @@ #' little interest and using a larger number for \code{n.min} than the default #' is usually wise. #' +#' @section Warning!: For the formatted equation to be valid, the fitted model +#' must be a polynomial, with or without intercept. If defined using +#' \code{poly()} the argument \code{raw = TRUE} must be passed. If defined +#' manually as powers of \code{x}, \strong{the terms must be in order of +#' increasing powers, with no missing intermediate power term.} Please, see +#' examples below. Currently, no check on the model is used to validate that +#' it is a polynomial, so failing to comply with this requirement results in +#' the silent output of an erroneous formatted equation. +#' #' @section Aesthetics: \code{stat_ma_eq} understands \code{x} and \code{y}, to #' be referenced in the \code{formula} while the \code{weight} aesthetic is #' ignored. Both \code{x} and \code{y} must be mapped to \code{numeric} @@ -189,16 +200,26 @@ #' stat_ma_line() + #' stat_ma_eq() #' +#' ggplot(my.data, aes(x, y)) + +#' geom_point() + +#' stat_ma_line() + +#' stat_ma_eq(mapping = use_label("eq")) +#' +#' ggplot(my.data, aes(x, y)) + +#' geom_point() + +#' stat_ma_line() + +#' stat_ma_eq(mapping = use_label("eq"), decreasing = TRUE) +#' #' # use_label() can assemble and map a combined label #' ggplot(my.data, aes(x, y)) + #' geom_point() + #' stat_ma_line(method = "MA") + -#' stat_ma_eq(use_label(c("eq", "R2", "P"))) +#' stat_ma_eq(mapping = use_label(c("eq", "R2", "P"))) #' #' ggplot(my.data, aes(x, y)) + #' geom_point() + #' stat_ma_line(method = "MA") + -#' stat_ma_eq(use_label(c("R2", "P", "theta", "method"))) +#' stat_ma_eq(mapping = use_label(c("R2", "P", "theta", "method"))) #' #' # using ranged major axis regression #' ggplot(my.data, aes(x, y)) + @@ -206,7 +227,7 @@ #' stat_ma_line(method = "RMA", #' range.y = "interval", #' range.x = "interval") + -#' stat_ma_eq(use_label(c("eq", "R2", "P")), +#' stat_ma_eq(mapping = use_label(c("eq", "R2", "P")), #' method = "RMA", #' range.y = "interval", #' range.x = "interval") @@ -215,7 +236,7 @@ #' ggplot(my.data, aes(x, y)) + #' geom_point() + #' stat_ma_line(method = "MA") + -#' stat_ma_eq(use_label(c("eq", "R2")), +#' stat_ma_eq(mapping = use_label(c("eq", "R2")), #' method = "MA", #' nperm = 0) #' @@ -224,13 +245,13 @@ #' geom_point() + #' stat_ma_line(formula = x ~ y) + #' stat_ma_eq(formula = x ~ y, -#' use_label(c("eq", "R2", "P"))) +#' mapping = use_label(c("eq", "R2", "P"))) #' #' # modifying both variables within aes() #' ggplot(my.data, aes(log(x + 10), log(y + 10))) + #' geom_point() + #' stat_poly_line() + -#' stat_poly_eq(use_label("eq"), +#' stat_poly_eq(mapping = use_label("eq"), #' eq.x.rhs = "~~log(x+10)", #' eq.with.lhs = "log(y+10)~~`=`~~") #' @@ -245,7 +266,7 @@ #' aes(x, y, shape = group, linetype = group, grp.label = group)) + #' geom_point() + #' stat_ma_line(color = "black") + -#' stat_ma_eq(use_label(c("grp", "eq", "R2"))) + +#' stat_ma_eq(mapping = use_label(c("grp", "eq", "R2"))) + #' theme_classic() #' #' # Inspecting the returned data using geom_debug() @@ -267,7 +288,7 @@ #' if (gginnards.installed) #' ggplot(my.data, aes(x, y)) + #' geom_point() + -#' stat_ma_eq(aes(label = after_stat(eq.label)), +#' stat_ma_eq(mapping = aes(label = after_stat(eq.label)), #' geom = "debug", #' output.type = "markdown") #' @@ -301,6 +322,7 @@ stat_ma_eq <- function(mapping = NULL, data = NULL, small.p = FALSE, coef.digits = 3, coef.keep.zeros = TRUE, + decreasing = FALSE, rr.digits = 2, theta.digits = 2, p.digits = max(1, ceiling(log10(nperm))), @@ -377,6 +399,7 @@ stat_ma_eq <- function(mapping = NULL, data = NULL, small.p = small.p, coef.digits = coef.digits, coef.keep.zeros = coef.keep.zeros, + decreasing = decreasing, rr.digits = rr.digits, theta.digits = theta.digits, p.digits = p.digits, @@ -419,6 +442,7 @@ ma_eq_compute_group_fun <- function(data, small.p, coef.digits, coef.keep.zeros, + decreasing, rr.digits, theta.digits, p.digits, @@ -445,7 +469,6 @@ ma_eq_compute_group_fun <- function(data, warning("Decimal mark must be one of '.' or ',', not: '", decimal.mark, "'") decimal.mark <- "." } -# range.sep <- c("." = ", ", "," = "; ")[decimal.mark] output.type <- if (!length(output.type)) { "expression" @@ -598,7 +621,7 @@ ma_eq_compute_group_fun <- function(data, b_0.constant = forced.origin) z <- cbind(z, tibble::as_tibble_row(coefs)) } else { - # set defaults needed to assemble the equation as a character string + # assemble the equation as a character string if (is.null(eq.x.rhs)) { eq.x.rhs <- build_eq.x.rhs(output.type = output.type, orientation = orientation) @@ -614,125 +637,50 @@ ma_eq_compute_group_fun <- function(data, lhs <- character(0) } - # build equation as a character string from the coefficient estimates eq.char <- coefs2poly_eq(coefs = coefs, coef.digits = coef.digits, coef.keep.zeros = coef.keep.zeros, + decreasing = decreasing, eq.x.rhs = eq.x.rhs, lhs = lhs, output.type = output.type, decimal.mark = decimal.mark) # build the other character strings - stopifnot(rr.digits > 0) - if (rr.digits < 2) { - warning("'rr.digits < 2' Likely information loss!") - } - stopifnot(theta.digits > 0) - if (theta.digits < 2) { - warning("'theta.digits < 2' Likely information loss!") - } - stopifnot(p.digits > 0) - if (p.digits < 2) { - warning("'p.digits < 2' Likely information loss!") - } - - if (output.type == "expression") { - rr.char <- sprintf_dm("\"%#.*f\"", rr.digits, rr, decimal.mark = decimal.mark) - theta.char <- sprintf_dm("\"%#.*f\"", theta.digits, theta, decimal.mark = decimal.mark) - if (p.digits == Inf) { - p.value.char <- sprintf_dm("%#.2e", p.value, decimal.mark = decimal.mark) - p.value.char <- paste(gsub("e", " %*% 10^{", p.value.char), "}", sep = "") - } else { - p.value.char <- sprintf_dm("\"%#.*f\"", p.digits, p.value, decimal.mark = decimal.mark) - } - } else { - rr.char <- sprintf_dm("%#.*f", rr.digits, rr, decimal.mark = decimal.mark) - theta.char <- sprintf_dm("%#.*f", theta.digits, theta, decimal.mark = decimal.mark) - if (p.digits == Inf) { - p.value.char <- sprintf_dm("%#.2e", p.value, decimal.mark = decimal.mark) - } else { - p.value.char <- sprintf_dm("%#.*f", p.digits, p.value, decimal.mark = decimal.mark) - } - } - - # build the data frames to return - if (output.type == "expression") { - z <- tibble::tibble(eq.label = eq.char, - rr.label = - # character(0) instead of "" avoids in paste() the insertion of sep for missing labels - ifelse(is.na(rr), character(0L), - paste(ifelse(small.r, "italic(r)^2", "italic(R)^2"), - ifelse(rr < 10^(-rr.digits) & rr != 0, - sprintf_dm("\"%.*f\"", rr.digits, 10^(-rr.digits), decimal.mark = decimal.mark), - rr.char), - sep = ifelse(rr < 10^(-rr.digits) & rr != 0, - "~`<`~", - "~`=`~"))), - p.value.label = - ifelse(is.na(p.value), character(0L), - paste(ifelse(small.p, "italic(p)[perm]", "italic(P)[perm]"), - ifelse(p.value < 10^(-p.digits), - sprintf_dm("\"%.*f\"", p.digits, 10^(-p.digits), decimal.mark = decimal.mark), - p.value.char), - sep = ifelse(p.value < 10^(-p.digits), - "~`<`~", - "~`=`~"))), - theta.label = paste("italic(theta)~`=`~", theta.char, sep = ""), - n.label = paste("italic(n)~`=`~\"", n, "\"", sep = ""), - grp.label = grp.label, - method.label = paste("\"method: ", method.name, "\"", sep = ""), - r.squared = rr, - theta = theta, - p.value = p.value, - n = n) - } else if (output.type %in% c("latex", "tex", "text", "tikz")) { - z <- tibble::tibble(eq.label = eq.char, - rr.label = - # character(0) instead of "" avoids in paste() the insertion of sep for missing labels - ifelse(is.na(rr), character(0L), - paste(ifelse(small.r, "r^2", "R^2"), - ifelse(rr < 10^(-rr.digits), as.character(10^(-rr.digits)), rr.char), - sep = ifelse(rr < 10^(-rr.digits), " < ", " = "))), - p.value.label = - ifelse(is.na(p.value), character(0L), - paste(ifelse(small.p, "p_{perm}", "P_{perm}"), - ifelse(p.value < 10^(-p.digits), as.character(10^(-p.digits)), p.value.char), - sep = ifelse(p.value < 10^(-p.digits), " < ", " = "))), - theta.label = paste("theta", theta.char, sep = " = "), - n.label = paste("n", n, sep = " = "), - grp.label = grp.label, - method.label = paste("method: ", method.name, sep = ""), - r.squared = rr, - theta = theta, - p.value = p.value, - n = n) - } else if (output.type == "markdown") { - z <- tibble::tibble(eq.label = eq.char, - rr.label = - # character(0) instead of "" avoids in paste() the insertion of sep for missing labels - ifelse(is.na(rr), character(0L), - paste(ifelse(small.r, "_r_2", "_R_2"), - ifelse(rr < 10^(-rr.digits), as.character(10^(-rr.digits)), rr.char), - sep = ifelse(rr < 10^(-rr.digits), " < ", " = "))), - p.value.label = - ifelse(is.na(p.value), character(0L), - paste(ifelse(small.p, "_p_perm", "_P_perm"), - ifelse(p.value < 10^(-p.digits), as.character(10^(-p.digits)), p.value.char), - sep = ifelse(p.value < 10^(-p.digits), " < ", " = "))), - theta.label = paste("_θ_", theta.char, sep = " = "), - n.label = paste("_n_ = ", n, sep = ""), - grp.label = grp.label, - method.label = paste("method: ", method.name, sep = ""), - r.squared = rr, - theta = theta, - p.value = p.value, - n = n) - } else { - warning("Unknown 'output.type' argument: ", output.type) - } + z <- data.frame(eq.label = eq.char, + rr.label = rr_label(value = rr, + small.r = small.r, + digits = rr.digits, + output.type = output.type, + decimal.mark = decimal.mark), + p.value.label = p_value_label(value = p.value, + subscript = "perm", + small.p = small.p, + digits = p.digits, + output.type = output.type, + decimal.mark = decimal.mark), + theta.label = italic_label(value = theta, + value.name = ifelse(output.type %in% c("latex", "text", "tikz"), + "\theta{}", "theta"), + digits = theta.digits, + fixed = TRUE, + output.type = output.type, + decimal.mark = decimal.mark), + n.label = italic_label(value = n, + value.name = "n", + digits = 0, + fixed = TRUE, + output.type = output.type, + decimal.mark = decimal.mark), + grp.label = grp.label, + method.label = paste("\"method: ", method.name, "\"", sep = ""), + r.squared = rr, + theta = theta, + p.value = p.value, + n = n) } + # add members common to numeric and other output types z[["fm.method"]] <- method.name z[["fm.class"]] <- fm.class[1] z[["fm.formula"]] <- formula.ls diff --git a/R/stat-multcomp.R b/R/stat-multcomp.R index 82b572c..affd5c5 100644 --- a/R/stat-multcomp.R +++ b/R/stat-multcomp.R @@ -740,30 +740,15 @@ multcomp_compute_fun <- } # build character strings - stopifnot(p.digits > 0) + stopifnot("'p.digits' must be a positive integer > 0" = p.digits > 0) if (p.digits < 2) { warning("'p.digits < 2' Likely information loss!") } if (output.type == "expression") { - if (p.digits == Inf) { - p.value.char <- sprintf_dm("%#.2e", z[["p.value"]], decimal.mark = decimal.mark) - p.value.char <- paste(gsub("e", " %*% 10^{", p.value.char), "}", sep = "") - } else { - p.value.char <- sprintf_dm("\"%#.*f\"", p.digits, z[["p.value"]], decimal.mark = decimal.mark) - } stars.char <- paste("\"", stars_pval(z[["p.value"]]), "\"", sep = "") - coefficients.char <- sprintf_dm("\"%#.*g\"", 3L, z[["coefficients"]], decimal.mark = decimal.mark) - tstat.char <- sprintf_dm("\"%#.*g\"", 3L, z[["tstat"]], decimal.mark = decimal.mark) } else { - if (p.digits == Inf) { - p.value.char <- sprintf_dm("%#.2e", z[["p.value"]], decimal.mark = decimal.mark) - } else { - p.value.char <- sprintf_dm("%#.*f", p.digits, z[["p.value"]], decimal.mark = decimal.mark) - } stars.char <- stars_pval(z[["p.value"]]) - coefficients.char <- sprintf_dm("%#.*g", 3L, z[["coefficients"]], decimal.mark = decimal.mark) - tstat.char <- sprintf_dm("%#.*g", 3L, z[["tstat"]], decimal.mark = decimal.mark) } # Build the labels @@ -772,47 +757,24 @@ multcomp_compute_fun <- if (output.type != "numeric") { z[["stars.label"]] <- stars.char z[["p.value.label"]] <- NA_character_ - } - if (output.type == "expression") { - for (i in seq_along(z[["p.value"]])) { - z[["p.value.label"]][i] <- - ifelse(is.na(z[["p.value"]][i]) || is.nan(z[["p.value"]][i]), "", - paste(paste(ifelse(small.p, "italic(p)[\"", "italic(P)[\""), - adj.label, "\"]", sep = ""), - ifelse(z[["p.value"]][i] < 10^(-p.digits), - sprintf_dm("\"%.*f\"", p.digits, 10^(-p.digits), decimal.mark = decimal.mark), - p.value.char[i]), - sep = ifelse(z[["p.value"]][i] < 10^(-p.digits), - "~`<`~", - "~`=`~"))) - } - # remove empty subscripts - z[["p.value.label"]] <- gsub("\\[\"\"\\]", "", z[["p.value.label"]]) - z[["delta.label"]] <- paste("Delta~`=`~", coefficients.char, sep = "") - z[["t.value.label"]] <- paste("italic(t)~`=`~", tstat.char, sep = "") - } else if (output.type %in% c("latex", "tex", "text", "tikz")) { - for (i in seq_along(z[["p.value"]])) { - z[["p.value.label"]][i] <- - ifelse(is.na(z[["p.value"]][i]) || is.nan(z[["p.value"]][i]), "", - paste(ifelse(small.p, "p", "P"), - ifelse(z[["p.value"]][i] < 10^(-p.digits), as.character(10^(-p.digits)), p.value.char[i]), - sep = ifelse(z[["p.value"]][i] < 10^(-p.digits), " < ", " = "))) - } - z[["delta.label"]] <- paste("\\Delta = ", coefficients.char, sep = "") - z[["t.value.label"]] <- paste("t = ", tstat.char, sep = "") - } else if (output.type == "markdown") { + for (i in seq_along(z[["p.value"]])) { - z[["p.value.label"]][i] <- - ifelse(is.na(z[["p.value"]][i]) | is.nan(z[["p.value"]][i]), "", - paste(ifelse(small.p, "_p_", "_P_"), - ifelse(z[["p.value"]][i] < 10^(-p.digits), as.character(10^(-p.digits)), p.value.char[i]), - sep = ifelse(z[["p.value"]][i] < 10^(-p.digits), " < ", " = "))) - } - z[["delta.label"]] <- paste("Δ = ", coefficients.char, sep = "") - z[["t.value.label"]] <- paste("_t_ = ", tstat.char, sep = "") - } else { - if (output.type != "numeric") { - stop("Unknown 'output.type' argument: ", output.type) + z[["p.value.label"]][i] <- p_value_label(value = z[["p.value"]][i], + subscript = adj.label, + small.p = small.p, + digits = p.digits, + output.type = output.type, + decimal.mark = decimal.mark) + z[["delta.label"]][i] <- italic_label(value = z[["coefficients"]][i], + value.name = "Delta", + digits = 3, + fixed = FALSE, + output.type = output.type, + decimal.mark = decimal.mark) + z[["t.value.label"]][i] <- t_value_label(value = z[["tstat"]][i], + digits = p.digits, + output.type = output.type, + decimal.mark = decimal.mark) } } @@ -835,8 +797,13 @@ multcomp_compute_fun <- Letters = get(label.type), reversed = TRUE)[["Letters"]] if (adj.method.legend) { - p.crit.label <- paste("\" \"*italic(P)[\"", adj.label, "\"]^{\"crit\"}~`=`~", - mc.critical.p.value, sep = "") + p.crit.label <- p_value_label(value = mc.critical.p.value, + subscript = adj.label, + superscript = "crit", + small.p = small.p, + digits = p.digits, + output.type = output.type, + decimal.mark = decimal.mark) z <- tibble::tibble(x = c(0.1, 1:num.levels), x.left.tip = NA_real_, x.right.tip = NA_real_, diff --git a/R/stat-poly-eq.R b/R/stat-poly-eq.R index 214c07b..4be83d0 100644 --- a/R/stat-poly-eq.R +++ b/R/stat-poly-eq.R @@ -52,6 +52,8 @@ #' the fitted coefficients and F-value. #' @param coef.keep.zeros logical Keep or drop trailing zeros when formatting #' the fitted coefficients and F-value. +#' @param decreasing logical It specifies the order of the terms in the +#' returned character string; in increasing (default) or decreasing powers. #' @param rr.digits,p.digits integer Number of digits after the decimal point to #' use for \eqn{R^2} and P-value in labels. If \code{Inf}, use exponential #' notation with three decimal places. @@ -139,6 +141,15 @@ #' interest and using larger values of \code{n.min} than the default is #' usually wise. #' +#' @section Warning!: For the formatted equation to be valid, the fitted model +#' must be a polynomial, with or without intercept. If defined using +#' \code{poly()} the argument \code{raw = TRUE} must be passed. If defined +#' manually as powers of \code{x}, \strong{the terms must be in order of +#' increasing powers, with no missing intermediate power term.} Please, see +#' examples below. Currently, no check on the model is used to validate that +#' it is a polynomial, so failing to comply with this requirement results in +#' the silent output of an erroneous formatted equation. +#' #' @references Originally written as an answer to question 7549694 at #' Stackoverflow but enhanced based on suggestions from users and my own #' needs. @@ -255,6 +266,12 @@ #' stat_poly_line(formula = formula) + #' stat_poly_eq(use_label("eq"), formula = formula) #' +#' # other labels +#' ggplot(my.data, aes(x, y)) + +#' geom_point() + +#' stat_poly_line(formula = formula) + +#' stat_poly_eq(use_label("eq"), formula = formula, decreasing = TRUE) +#' #' ggplot(my.data, aes(x, y)) + #' geom_point() + #' stat_poly_line(formula = formula) + @@ -468,6 +485,7 @@ stat_poly_eq <- function(mapping = NULL, data = NULL, rsquared.conf.level = 0.95, coef.digits = 3, coef.keep.zeros = TRUE, + decreasing = FALSE, rr.digits = 2, f.digits = 3, p.digits = 3, @@ -563,6 +581,7 @@ stat_poly_eq <- function(mapping = NULL, data = NULL, rsquared.conf.level = rsquared.conf.level, coef.digits = coef.digits, coef.keep.zeros = coef.keep.zeros, + decreasing = decreasing, rr.digits = rr.digits, f.digits = f.digits, p.digits = p.digits, @@ -605,6 +624,7 @@ poly_eq_compute_group_fun <- function(data, rsquared.conf.level, coef.digits, coef.keep.zeros, + decreasing, rr.digits, f.digits, p.digits, @@ -626,7 +646,6 @@ poly_eq_compute_group_fun <- function(data, warning("Decimal mark must be one of '.' or ',', not: '", decimal.mark, "'") decimal.mark <- "." } - range.sep <- c("." = ", ", "," = "; ")[decimal.mark] if (orientation == "x") { if (length(unique(data$x)) < n.min) { @@ -746,14 +765,15 @@ poly_eq_compute_group_fun <- function(data, } else { f.value <- f.df1 <- f.df2 <- p.value <- NA_real_ } - if ("r.squared" %in% names(fm.summary) - ) { + if ("r.squared" %in% names(fm.summary)) { rr <- fm.summary[["r.squared"]] if (!all(is.finite(c(f.value, f.df1, f.df2))) || rsquared.conf.level <= 0 ) { rr.confint.low <- rr.confint.high <- NA_real_ } else { + # error handler needs to be added as ci_rsquared() will call stop on non-convergence + # or alternatively implement a non-stop version of ci_rsquared() rr.confint <- confintr::ci_rsquared(x = f.value, df1 = f.df1, @@ -808,7 +828,7 @@ poly_eq_compute_group_fun <- function(data, b_0.constant = forced.origin) z <- cbind(z, tibble::as_tibble_row(coefs)) } else { - # set defaults needed to assemble the equation as a character string + # assemble the fitted polynomial equation as a character string if (is.null(eq.x.rhs)) { eq.x.rhs <- build_eq.x.rhs(output.type = output.type, orientation = orientation) @@ -824,214 +844,70 @@ poly_eq_compute_group_fun <- function(data, lhs <- character(0) } - # build equation as a character string from the coefficient estimates eq.char <- coefs2poly_eq(coefs = coefs, coef.digits = coef.digits, coef.keep.zeros = coef.keep.zeros, + decreasing = decreasing, eq.x.rhs = eq.x.rhs, lhs = lhs, output.type = output.type, decimal.mark = decimal.mark) - # build the other character strings - stopifnot(rr.digits > 0) - if (rr.digits < 2) { - warning("'rr.digits < 2' Likely information loss!") - } - stopifnot(f.digits > 0) - if (f.digits < 2) { - warning("'f.digits < 2' Likely information loss!") - } - stopifnot(p.digits > 0) - if (p.digits < 2) { - warning("'p.digits < 2' Likely information loss!") - } - - if (output.type == "expression") { - rr.char <- sprintf_dm("\"%#.*f\"", rr.digits, rr, decimal.mark = decimal.mark) - adj.rr.char <- sprintf_dm("\"%#.*f\"", rr.digits, adj.rr, decimal.mark = decimal.mark) - rr.confint.chr <- paste(sprintf_dm("%#.*f", - rr.digits, rr.confint.low, decimal.mark = decimal.mark), - sprintf_dm("%#.*f", - rr.digits, rr.confint.high, decimal.mark = decimal.mark), - sep = range.sep) - if (as.logical((rsquared.conf.level * 100) %% 1)) { - conf.level.digits = 1L - } else { - conf.level.digits = 0L - } - conf.level.chr <- sprintf_dm("%.*f", conf.level.digits, rsquared.conf.level * 100, decimal.mark = decimal.mark) - AIC.char <- sprintf_dm("\"%.4g\"", AIC, decimal.mark = decimal.mark) - BIC.char <- sprintf_dm("\"%.4g\"", BIC, decimal.mark = decimal.mark) - f.value.char <- sprintf_dm("\"%#.*g\"", f.digits, f.value, decimal.mark = decimal.mark) - if (grepl("e", f.value.char)) { - f.value.char <- sprintf_dm("%#.*e", f.digits, f.value, decimal.mark = decimal.mark) - f.value.char <- paste(gsub("e", " %*% 10^{", f.value.char), "}", sep = "") - } - f.df1.char <- as.character(f.df1) - f.df2.char <- as.character(f.df2) - if (p.digits == Inf) { - p.value.char <- sprintf_dm("%#.2e", p.value, decimal.mark = decimal.mark) - p.value.char <- paste(gsub("e", " %*% 10^{", p.value.char), "}", sep = "") - } else { - p.value.char <- sprintf_dm("\"%#.*f\"", p.digits, p.value, decimal.mark = decimal.mark) - } - } else { - rr.char <- sprintf_dm("%#.*f", rr.digits, rr, decimal.mark = decimal.mark) - adj.rr.char <- sprintf_dm("%#.*f", rr.digits, adj.rr, decimal.mark = decimal.mark) - rr.confint.chr <- paste(sprintf_dm("%#.*f", - rr.digits, rr.confint.low, decimal.mark = decimal.mark), - sprintf_dm("%#.*f", - rr.digits, rr.confint.high, decimal.mark = decimal.mark), - sep = range.sep) - if (as.logical((rsquared.conf.level * 100) %% 1)) { - conf.level.digits = 1L - } else { - conf.level.digits = 0L - } - conf.level.chr <- sprintf_dm("%.*f", conf.level.digits, rsquared.conf.level * 100, decimal.mark = decimal.mark) - AIC.char <- sprintf_dm("%.4g", AIC, decimal.mark = decimal.mark) - BIC.char <- sprintf_dm("%.4g", BIC, decimal.mark = decimal.mark) - f.value.char <- sprintf_dm("%#.*g", f.digits, f.value, decimal.mark = decimal.mark) - f.df1.char <- as.character(f.df1) - f.df2.char <- as.character(f.df2) - if (p.digits == Inf) { - p.value.char <- sprintf_dm("%#.2e", p.value, decimal.mark = decimal.mark) - } else { - p.value.char <- sprintf_dm("%#.*f", p.digits, p.value, decimal.mark = decimal.mark) - } - } - - # build the data frames to return - if (output.type == "expression") { - z <- tibble::tibble(eq.label = eq.char, - rr.label = - # character(0) instead of "" avoids in paste() the insertion of sep for missing labels - ifelse(is.na(rr) || is.nan(rr), character(0L), - paste(ifelse(small.r, "italic(r)^2", "italic(R)^2"), - ifelse(rr < 10^(-rr.digits) & rr != 0, - sprintf_dm("\"%.*f\"", rr.digits, 10^(-rr.digits), decimal.mark = decimal.mark), - rr.char), - sep = ifelse(rr < 10^(-rr.digits) & rr != 0, - "~`<`~", - "~`=`~"))), - adj.rr.label = - ifelse(is.na(adj.rr) || is.nan(adj.rr), character(0L), - paste(ifelse(small.r, "italic(r)[adj]^2", "italic(R)[adj]^2"), - ifelse(adj.rr < 10^(-rr.digits) & adj.rr != 0, - sprintf_dm("\"%.*f\"", rr.digits, 10^(-rr.digits), decimal.mark = decimal.mark), - adj.rr.char), - sep = ifelse(adj.rr < 10^(-rr.digits) & adj.rr != 0, - "~`<`~", - "~`=`~"))), - rr.confint.label = - paste("\"", conf.level.chr, "% CI ", CI.brackets[1], rr.confint.chr, CI.brackets[2], "\"", sep = ""), - AIC.label = - ifelse(is.na(AIC) || is.nan(AIC), character(0L), - paste("AIC", AIC.char, sep = "~`=`~")), - BIC.label = - ifelse(is.na(BIC) || is.nan(BIC), character(0L), - paste("BIC", BIC.char, sep = "~`=`~")), - f.value.label = - ifelse(is.na(f.value) || is.nan(f.value), character(0L), - paste("italic(F)[", f.df1.char, - "*\",\"*", f.df2.char, - "]~`=`~", f.value.char, sep = "")), - p.value.label = - ifelse(is.na(p.value) || is.nan(p.value), character(0L), - paste(ifelse(small.p, "italic(p)", "italic(P)"), - ifelse(p.value < 10^(-p.digits), - sprintf_dm("\"%.*f\"", p.digits, 10^(-p.digits), decimal.mark = decimal.mark), - p.value.char), - sep = ifelse(p.value < 10^(-p.digits), - "~`<`~", - "~`=`~"))), - n.label = paste("italic(n)~`=`~\"", n, "\"", sep = ""), - grp.label = grp.label, - method.label = paste("\"method: ", method.name, "\"", sep = ""), - r.squared = rr, - adj.r.squared = adj.rr, - p.value = p.value, - n = n) - } else if (output.type %in% c("latex", "tex", "text", "tikz")) { - z <- tibble::tibble(eq.label = eq.char, - rr.label = - # character(0) instead of "" avoids in paste() the insertion of sep for missing labels - ifelse(is.na(rr) || is.nan(rr), character(0L), - paste(ifelse(small.r, "r^2", "R^2"), - ifelse(rr < 10^(-rr.digits), as.character(10^(-rr.digits)), rr.char), - sep = ifelse(rr < 10^(-rr.digits), " < ", " = "))), - adj.rr.label = - ifelse(is.na(adj.rr) || is.nan(adj.rr), character(0L), - paste(ifelse(small.r, "r_{adj}^2", "R_{adj}^2"), - ifelse(adj.rr < 10^(-rr.digits), as.character(10^(-rr.digits)), adj.rr.char), - sep = ifelse(adj.rr < 10^(-rr.digits), " < ", " = "))), - rr.confint.label = - paste(conf.level.chr, "% CI ", CI.brackets[1], rr.confint.chr, CI.brackets[2], sep = ""), - AIC.label = - ifelse(is.na(AIC) || is.nan(AIC), character(0L), - paste("AIC", AIC.char, sep = " = ")), - BIC.label = - ifelse(is.na(BIC) || is.nan(BIC), character(0L), - paste("BIC", BIC.char, sep = " = ")), - f.value.label = - ifelse(is.na(f.value) || is.nan(f.value), character(0L), - paste("F_{", f.df1.char, ",", f.df2.char, - "} = ", f.value.char, sep = "")), - p.value.label = - ifelse(is.na(p.value), character(0L), - paste(ifelse(small.p, "p", "P"), - ifelse(p.value < 10^(-p.digits), as.character(10^(-p.digits)), p.value.char), - sep = ifelse(p.value < 10^(-p.digits), " < ", " = "))), - n.label = paste("n = ", n, sep = ""), - grp.label = grp.label, - method.label = paste("method: ", method.name, sep = ""), - r.squared = rr, - adj.r.squared = adj.rr, - p.value = p.value, - n = n) - } else if (output.type == "markdown") { - z <- tibble::tibble(eq.label = eq.char, - rr.label = - # character(0) instead of "" avoids in paste() the insertion of sep for missing labels - ifelse(is.na(rr) || is.nan(rr), character(0L), - paste(ifelse(small.r, "_r_2", "_R_2"), - ifelse(rr < 10^(-rr.digits), as.character(10^(-rr.digits)), rr.char), - sep = ifelse(rr < 10^(-rr.digits), " < ", " = "))), - adj.rr.label = - ifelse(is.na(adj.rr) || is.nan(adj.rr), character(0L), - paste(ifelse(small.r, "_r_2adj", "_R_2adj"), - ifelse(adj.rr < 10^(-rr.digits), as.character(10^(-rr.digits)), adj.rr.char), - sep = ifelse(adj.rr < 10^(-rr.digits), " < ", " = "))), - rr.confint.label = - paste(conf.level.chr, "% CI ", CI.brackets[1], rr.confint.chr, CI.brackets[2], sep = ""), - AIC.label = - ifelse(is.na(AIC) || is.nan(AIC), character(0L), - paste("AIC", AIC.char, sep = " = ")), - BIC.label = - ifelse(is.na(BIC) || is.nan(BIC), character(0L), - paste("BIC", BIC.char, sep = " = ")), - f.value.label = - ifelse(is.na(f.value) || is.nan(f.value), character(0L), - paste("_F_", f.df1.char, ",", f.df2.char, - " = ", f.value.char, sep = "")), - p.value.label = - ifelse(is.na(p.value) || is.nan(p.value), character(0L), - paste(ifelse(small.p, "_p_", "_P_"), - ifelse(p.value < 10^(-p.digits), as.character(10^(-p.digits)), p.value.char), - sep = ifelse(p.value < 10^(-p.digits), " < ", " = "))), - n.label = paste("_n_ = ", n, sep = ""), - grp.label = grp.label, - method.label = paste("method: ", method.name, sep = ""), - r.squared = rr, - adj.r.squared = adj.rr, - p.value = p.value, - n = n) - } else { - warning("Unknown 'output.type' argument: ", output.type) - } - } - + # assemble the data frame to return + z <- data.frame(eq.label = eq.char, + rr.label = rr_label(value = rr, + small.r = small.r, + digits = rr.digits, + output.type = output.type, + decimal.mark = decimal.mark), + adj.rr.label = adj_rr_label(value = adj.rr, + small.r = small.r, + digits = rr.digits, + output.type = output.type, + decimal.mark = decimal.mark), + rr.confint.label = rr_ci_label(value = c(rr.confint.low, rr.confint.high), + conf.level = rsquared.conf.level, + range.brackets = CI.brackets, + range.sep = NULL, + digits = rr.digits, + output.type = output.type, + decimal.mark = decimal.mark), + AIC.label = plain_label(value = AIC, + value.name = "AIC", + digits = 4, + output.type = output.type, + decimal.mark = decimal.mark), + BIC.label = plain_label(value = BIC, + value.name = "BIC", + digits = 4, + output.type = output.type, + decimal.mark = decimal.mark), + f.value.label = f_value_label(value = f.value, + df1 = f.df1, + df2 = f.df2, + digits = f.digits, + output.type = output.type, + decimal.mark = decimal.mark), + p.value.label = p_value_label(value = p.value, + small.p = small.p, + digits = p.digits, + output.type = output.type, + decimal.mark = decimal.mark), + n.label = italic_label(value = n, + value.name = "n", + digits = 0, + fixed = TRUE, + output.type = output.type, + decimal.mark = decimal.mark), + grp.label = grp.label, + method.label = paste("\"method: ", method.name, "\"", sep = ""), + r.squared = rr, + adj.r.squared = adj.rr, + p.value = p.value, + n = n) + } + + # add members common to numeric and other output types z[["fm.method"]] <- method.name z[["fm.class"]] <- fm.class[1] z[["fm.formula"]] <- formula.ls @@ -1103,158 +979,3 @@ StatPolyEq <- optional_aes = "grp.label" ) -### Utility functions shared between stat_poly_eq() and stat_quant_eq() -# when stable will be exported -# -build_eq.x.rhs <- function(output.type = "expression", - orientation = "x") { - if (orientation == "x") { - if (output.type == "expression") { - "~italic(x)" - } else if (output.type == "markdown") { - "_x_" - } else{ - " x" - } - } else if (orientation == "y") { - if (output.type == "expression") { - "~italic(y)" - } else if (output.type == "markdown") { - "_y_" - } else{ - " y" - } - } -} - -build_lhs <- function(output.type = "expression", - orientation = "x") { - if (orientation == "x") { - if (output.type == "expression") { - "italic(y)~`=`~" - } else if (output.type %in% c("latex", "tex", "tikz", "text")) { - "y = " - } else if (output.type == "markdown") { - "_y_ = " - } - } else if (orientation == "y") { - if (output.type == "expression") { - "italic(x)~`=`~" - } else if (output.type %in% c("latex", "tex", "tikz", "text")) { - "x = " - } else if (output.type == "markdown") { - "_x_ = " - } - } -} - -coefs2poly_eq <- function(coefs, - coef.digits = 3L, - coef.keep.zeros = TRUE, - eq.x.rhs = "x", - lhs = "y~`=`~", - output.type = "expression", - decimal.mark = ".") { - # build equation as a character string from the coefficient estimates - stopifnot(coef.digits > 0) - if (coef.digits < 3) { - warning("'coef.digits < 3' Likely information loss!") - } - eq.char <- as.character(polynom::as.polynomial(coefs), - digits = coef.digits, - keep.zeros = coef.keep.zeros) - eq.char <- typeset_numbers(eq.char, output.type) - if (output.type != "expression") { # parse() does the conversion - if (decimal.mark == ".") { - eq.char <- gsub(",", decimal.mark, eq.char, fixed = TRUE) - } else { - eq.char <- gsub(".", decimal.mark, eq.char, fixed = TRUE) - } - } - - if (eq.x.rhs != "x") { - eq.char <- gsub("x", eq.x.rhs, eq.char, fixed = TRUE) - } - if (length(lhs)) { - eq.char <- paste(lhs, eq.char, sep = "") - } - - eq.char -} - -# based on idea in answer by slamballais to Stackoverflow question -# at https://stackoverflow.com/questions/67942485/ -# -# This is an edit of the code in package 'polynom' so that trailing zeros are -# retained during the conversion -#' @noRd -#' @noMd -#' @export -#' @method as.character polynomial -#' -as.character.polynomial <- function (x, - decreasing = FALSE, - digits = 3, - keep.zeros = TRUE, - ...) { - if (keep.zeros) { - p <- sprintf("%#.*g", digits, x) - } else { - p <- sprintf("%.*g", digits, x) - } - lp <- length(p) - 1 - names(p) <- 0:lp - p <- p[as.numeric(p) != 0] - if (length(p) == 0) - return("0") - if (decreasing) - p <- rev(p) - signs <- ifelse(as.numeric(p) < 0, "- ", "+ ") - signs[1] <- if (signs[1] == "- ") "-" else "" - np <- names(p) - pow <- paste("x^", np, sep = "") - pow[np == "0"] <- "" - pow[np == "1"] <- "x" - stars <- rep.int("*", length(p)) - stars[p == "" | pow == ""] <- "" - p <- gsub("^-", "", p) - paste0(signs, p, stars, pow, collapse = " ") -} - -# exponential number notation to typeset equivalent: Protecting trailing zeros -# in negative numbers is more involved than I would like. Not only we need to -# enclose numbers in quotations marks but we also need to replace dashes with -# the minus character. I am not sure we can do the replacement portably, but -# that recent R supports UTF gives some hope. -# -typeset_numbers <- function(eq.char, output.type) { - if (output.type == "markdown") { - eq.char <- gsub("e([+-]?)[0]([1-9]*)", "×10\\1\\2", eq.char) - eq.char <- gsub("[:^]([0-9]*)", "\\1", eq.char) - eq.char <- gsub("*", " ", eq.char, fixed = TRUE) - eq.char <- gsub(" ", "", eq.char, fixed = TRUE) - } else { - eq.char <- gsub("e([+-]?[0-9]*)", "%*% 10^{\\1}", eq.char) - # muliplication symbol - if (output.type %in% c("latex", "tikz")) { - eq.char <- gsub("%*%", "\\times{}", eq.char, fixed = TRUE) - eq.char <- gsub("*", "", eq.char, fixed = TRUE) - } else if (output.type == "text") { - eq.char <- gsub("[{]|[}]", "", eq.char, fixed = FALSE) - eq.char <- gsub("%*%", "", eq.char, fixed = TRUE) - eq.char <- gsub("*", " ", eq.char, fixed = TRUE) - eq.char <- gsub(" ", " ", eq.char, fixed = TRUE) - } - } - eq.char -} - -# replace decimal mark used by sprintf() if needed -sprintf_dm <- function(fmt, ..., decimal.mark = ".") { - if (decimal.mark != ".") { - gsub(".", decimal.mark, sprintf(fmt, ...), fixed = TRUE) - } else { - # in case OS locale uses "," - gsub(",", ".", sprintf(fmt, ...), fixed = TRUE) - } -} diff --git a/R/stat-quant-eq.R b/R/stat-quant-eq.R index a6df053..16bfd44 100644 --- a/R/stat-quant-eq.R +++ b/R/stat-quant-eq.R @@ -55,6 +55,8 @@ #' the fitted coefficients and rho in labels. #' @param coef.keep.zeros logical Keep or drop trailing zeros when formatting #' the fitted coefficients and F-value. +#' @param decreasing logical It specifies the order of the terms in the +#' returned character string; in increasing (default) or decreasing powers. #' @param label.x,label.y \code{numeric} with range 0..1 "normalized parent #' coordinates" (npc units) or character if using \code{geom_text_npc()} or #' \code{geom_label_npc()}. If using \code{geom_text()} or \code{geom_label()} @@ -133,6 +135,15 @@ #' @references Written as an answer to question 65695409 by Mark Neal at #' Stackoverflow. #' +#' @section Warning!: For the formatted equations to be valid, the fitted model +#' must be a polynomial, with or without intercept. If defined using +#' \code{poly()} the argument \code{raw = TRUE} must be passed. If defined +#' manually as powers of \code{x}, \strong{the terms must be in order of +#' increasing powers, with no missing intermediate power term.} Please, see +#' examples below. Currently, no check on the model is used to validate that +#' it is a polynomial, so failing to comply with this requirement results in +#' the silent output of an erroneous formatted equation. +#' #' @section Aesthetics: \code{stat_quant_eq()} understands \code{x} and \code{y}, #' to be referenced in the \code{formula} and \code{weight} passed as argument #' to parameter \code{weights} of \code{rq()}. All three must be mapped to @@ -226,7 +237,17 @@ #' ggplot(my.data, aes(x, y)) + #' geom_point() + #' stat_quant_line() + -#' stat_quant_eq(use_label(c("eq", "method"))) +#' stat_quant_eq(mapping = use_label("eq")) +#' +#' ggplot(my.data, aes(x, y)) + +#' geom_point() + +#' stat_quant_line() + +#' stat_quant_eq(mapping = use_label("eq"), decreasing = TRUE) +#' +#' ggplot(my.data, aes(x, y)) + +#' geom_point() + +#' stat_quant_line() + +#' stat_quant_eq(mapping = use_label(c("eq", "method"))) #' #' # same formula as default #' ggplot(my.data, aes(x, y)) + @@ -243,15 +264,15 @@ #' # using color #' ggplot(my.data, aes(x, y)) + #' geom_point() + -#' stat_quant_line(aes(color = after_stat(quantile.f))) + -#' stat_quant_eq(aes(color = after_stat(quantile.f))) + +#' stat_quant_line(mapping = aes(color = after_stat(quantile.f))) + +#' stat_quant_eq(mapping = aes(color = after_stat(quantile.f))) + #' labs(color = "Quantiles") #' #' # location and colour #' ggplot(my.data, aes(x, y)) + #' geom_point() + -#' stat_quant_line(aes(color = after_stat(quantile.f))) + -#' stat_quant_eq(aes(color = after_stat(quantile.f)), +#' stat_quant_line(mapping = aes(color = after_stat(quantile.f))) + +#' stat_quant_eq(mapping = aes(color = after_stat(quantile.f)), #' label.y = "bottom", label.x = "right") + #' labs(color = "Quantiles") #' @@ -301,7 +322,7 @@ #' grp.label = group)) + #' geom_point() + #' stat_quant_band(formula = formula, color = "black", linewidth = 0.75) + -#' stat_quant_eq(use_label(c("grp", "eq"), sep = "*\": \"*"), +#' stat_quant_eq(mapping = use_label(c("grp", "eq"), sep = "*\": \"*"), #' formula = formula) + #' expand_limits(y = 3) + #' theme_classic() @@ -312,7 +333,7 @@ #' ggplot(my.data, aes(x, y + 1)) + #' geom_point() + #' stat_quant_line(formula = formula.trans) + -#' stat_quant_eq(use_label("eq"), +#' stat_quant_eq(mapping = use_label("eq"), #' formula = formula.trans, #' eq.x.rhs = "~x^2", #' eq.with.lhs = "y + 1~~`=`~~") @@ -333,10 +354,10 @@ #' ggplot(my.data, aes(x, y2, color = group, grp.label = group)) + #' geom_point() + #' stat_quant_line(method = "rq", formula = formula, -#' quantiles = c(0.05, 0.5, 0.95), -#' linewidth = 0.5) + -#' stat_quant_eq(aes(label = paste(after_stat(grp.label), "*\": \"*", -#' after_stat(eq.label), sep = "")), +#' quantiles = c(0.05, 0.5, 0.95), +#' linewidth = 0.5) + +#' stat_quant_eq(mapping = aes(label = paste(after_stat(grp.label), "*\": \"*", +#' after_stat(eq.label), sep = "")), #' quantiles = c(0.05, 0.5, 0.95), #' formula = formula, size = 3) #' @@ -345,9 +366,9 @@ #' geom_point() + #' stat_quant_band(method = "rq", formula = formula, #' quantiles = c(0.05, 0.5, 0.95)) + -#' stat_quant_eq(aes(label = sprintf("%s*\": \"*%s", -#' after_stat(grp.label), -#' after_stat(eq.label))), +#' stat_quant_eq(mapping = aes(label = sprintf("%s*\": \"*%s", +#' after_stat(grp.label), +#' after_stat(eq.label))), #' quantiles = c(0.05, 0.5, 0.95), #' formula = formula, size = 3) #' @@ -377,7 +398,7 @@ #' if (gginnards.installed) #' ggplot(my.data, aes(x, y)) + #' geom_point() + -#' stat_quant_eq(aes(label = after_stat(eq.label)), +#' stat_quant_eq(mapping = aes(label = after_stat(eq.label)), #' formula = formula, geom = "debug", #' output.type = "markdown") #' @@ -419,7 +440,8 @@ stat_quant_eq <- function(mapping = NULL, data = NULL, eq.x.rhs = NULL, coef.digits = 3, coef.keep.zeros = TRUE, - rho.digits = 2, + decreasing = FALSE, + rho.digits = 4, label.x = "left", label.y = "top", label.x.npc = NULL, label.y.npc = NULL, hstep = 0, @@ -487,6 +509,7 @@ stat_quant_eq <- function(mapping = NULL, data = NULL, eq.x.rhs = eq.x.rhs, coef.digits = coef.digits, coef.keep.zeros = coef.keep.zeros, + decreasing = decreasing, rho.digits = rho.digits, label.x = label.x, label.y = label.y, @@ -524,6 +547,7 @@ quant_eq_compute_group_fun <- function(data, eq.x.rhs, coef.digits, coef.keep.zeros, + decreasing, rho.digits, label.x, label.y, @@ -544,7 +568,6 @@ quant_eq_compute_group_fun <- function(data, warning("Decimal mark must be one of '.' or ',', not: '", decimal.mark, "'") decimal.mark <- "." } -# range.sep <- c("." = ", ", "," = "; ")[decimal.mark] num.quantiles <- length(quantiles) @@ -747,72 +770,60 @@ quant_eq_compute_group_fun <- function(data, warning("'coef.digits < 3' Likely information loss!") } - eq.char <- AIC.char <- rho.char <- character(num.quantiles) + qtl.char <- n.char <- eq.char <- AIC.char <- rho.char <- character(num.quantiles) for (q in seq_along(quantiles)) { # build equation as a character string from the coefficient estimates eq.char[q] <- coefs2poly_eq(coefs = coefs.ls[[q]], coef.digits = coef.digits, coef.keep.zeros = coef.keep.zeros, + decreasing = decreasing, eq.x.rhs = eq.x.rhs, lhs = lhs, output.type = output.type, decimal.mark = decimal.mark) - - if (output.type == "expression" && coef.keep.zeros) { - AIC.char[q] <- sprintf_dm("\"%.4g\"", AIC[q], decimal.mark = decimal.mark) - rho.char[q] <- sprintf_dm("\"%#.3g\"", rho[q], decimal.mark = decimal.mark) - } else { - AIC.char[q] <- sprintf_dm("%.4g", AIC[q], decimal.mark = decimal.mark) - rho.char[q] <- sprintf_dm("%#.3g", rho[q], decimal.mark = decimal.mark) - } + # build other label that vary with quantiles + AIC.char[q] <- plain_label(value = AIC[q], + value.name = "AIC", + digits = 4, + fixed = FALSE, + output.type = output.type, + decimal.mark = decimal.mark) + rho.char[q] <- r_label(value = rho[q], + method = "spearman", + digits = rho.digits, + fixed = FALSE, + output.type = output.type, + decimal.mark = decimal.mark) + n.char[q] <- italic_label(value = n, + value.name = "n", + digits = 0, + fixed = TRUE, + output.type = output.type, + decimal.mark = decimal.mark) + qtl.char[q] <- italic_label(value = quantiles[q], + value.name = "q", + digits = 2, + fixed = TRUE, + output.type = output.type, + decimal.mark = decimal.mark) } # build data frames to return - if (output.type == "expression") { - z <- tibble::tibble(eq.label = eq.char, - AIC.label = paste("AIC", AIC.char, sep = "~`=`~"), - rho.label = paste("rho", rho.char, sep = "~`=`~"), - n.label = paste("italic(n)~`=`~", n, sep = ""), - grp.label = if (any(grp.label != "")) - paste(grp.label, - sprintf_dm("italic(q)~`=`~\"%.2f\"", quantiles, decimal.mark = decimal.mark), - sep = "*\", \"*") - else - sprintf_dm("italic(q)~`=`~\"%.2f\"", quantiles, decimal.mark = decimal.mark), - method.label = paste("\"method: ", method.name, "\"", sep = ""), - rq.method = rq.method, - quantile = quantiles, - quantile.f = quantiles.f, - n = n) - } else if (output.type %in% c("latex", "tex", "text", "tikz")) { - z <- tibble::tibble(eq.label = eq.char, - AIC.label = paste("AIC", AIC.char, sep = " = "), - rho.label = paste("rho", rho.char, sep = " = "), - n.label = paste("n = ", n, sep = ""), - grp.label = paste(grp.label, - sprintf_dm("q = %.2f", quantiles, decimal.mark = decimal.mark)), - method.label = paste("method: ", method.name, sep = ""), - rq.method = rq.method, - quantile = quantiles, - quantile.f = quantiles.f, - n = n) - } else if (output.type == "markdown") { - z <- tibble::tibble(eq.label = eq.char, - AIC.label = paste("AIC", AIC.char, sep = " = "), - rho.label = paste("rho", rho.char, sep = " = "), - n.label = paste("_n_ = ", n, sep = ""), - grp.label = paste(grp.label, - sprintf_dm("q = %.2f", quantiles, decimal.mark = decimal.mark)), - method.label = paste("method: ", method.name, sep = ""), - rq.method = rq.method, - quantile = quantiles, - quantile.f = quantiles.f, - n = n) - } else { - warning("Unknown 'output.type' argument: ", output.type) - } + z <- data.frame(eq.label = eq.char, + AIC.label = AIC.char, + rho.label = rho.char, + n.label = n.char, + grp.label = grp.label, + qtl.label = qtl.char, + method.label = paste("\"method: ", method.name, "\"", sep = ""), + rho = rho, + rq.method = rq.method, + quantile = quantiles, + quantile.f = quantiles.f, + n = n) } + # add members common to numeric and other output types z[["fm.method"]] <- method.name z[["fm.class"]] <- fm.class[1] z[["fm.formula"]] <- formula.ls diff --git a/R/utilities-eq-label.R b/R/utilities-eq-label.R new file mode 100644 index 0000000..0471806 --- /dev/null +++ b/R/utilities-eq-label.R @@ -0,0 +1,212 @@ +#' Left and right hand sides of model equations +#' +#' @param output.type character One of "expression", "latex", "tex", "text", +#' "tikz", "markdown". +#' @param orientation character \code{"x"} or \code{"y"}, indicating +#' the aesthetic onto which the explanatory variable is mapped. +#' +#' @return A \code{character} string. +#' +#' @keywords internal +#' +build_eq.x.rhs <- function(output.type = "expression", + orientation = "x") { + if (orientation == "x") { + if (output.type == "expression") { + "~italic(x)" + } else if (output.type == "markdown") { + "_x_" + } else{ + " x" + } + } else if (orientation == "y") { + if (output.type == "expression") { + "~italic(y)" + } else if (output.type == "markdown") { + "_y_" + } else{ + " y" + } + } +} + +#' @rdname build_eq.x.rhs +#' +#' @return A \code{character} string. +#' +build_lhs <- function(output.type = "expression", + orientation = "x") { + if (orientation == "x") { + if (output.type == "expression") { + "italic(y)~`=`~" + } else if (output.type %in% c("latex", "tex", "tikz", "text")) { + "y = " + } else if (output.type == "markdown") { + "_y_ = " + } + } else if (orientation == "y") { + if (output.type == "expression") { + "italic(x)~`=`~" + } else if (output.type %in% c("latex", "tex", "tikz", "text")) { + "x = " + } else if (output.type == "markdown") { + "_x_ = " + } + } +} + +#' Convert a polynomial into character string +#' +#' Differs from \code{polynom::as.character.polynomial()} in that trailing zeros +#' are preserved. +#' +#' @note This is an edit of the code in package 'polynom' so that trailing zeros are +#' retained during the conversion. It is not defined using a different name +#' so as not to interfere with the original. +#' @param x a \code{polynomial} object. +#' @param decreasing logical It specifies the order of the terms; in increasing +#' (default) or decreasing powers. +#' @param digits integer Giving the number of significant digits to use for +#' printing. +#' @param keep.zeros logical It indicates if zeros are to be retained in the +#' formatted coefficients. +#' +#' @return A \code{character} string. +#' +#' @examples +#' poly2character(1:3) +#' poly2character(1:3, decreasing = TRUE) +#' +#' @export +#' +poly2character <- function (x, + decreasing = FALSE, + digits = 3, + keep.zeros = TRUE) { + if (keep.zeros) { + p <- sprintf("%#.*g", digits, x) + } else { + p <- sprintf("%.*g", digits, x) + } + lp <- length(p) - 1 + names(p) <- 0:lp + p <- p[as.numeric(p) != 0] + if (length(p) == 0) + return("0") + if (decreasing) + p <- rev(p) + signs <- ifelse(as.numeric(p) < 0, "- ", "+ ") + signs[1] <- if (signs[1] == "- ") "-" else "" + np <- names(p) + pow <- paste("x^", np, sep = "") + pow[np == "0"] <- "" + pow[np == "1"] <- "x" + stars <- rep.int("*", length(p)) + stars[p == "" | pow == ""] <- "" + p <- gsub("^-", "", p) + paste0(signs, p, stars, pow, collapse = " ") +} + + +#' Typeset/format numbers preserving trailing zeros +#' +#' @param eq.char character A polynomial model equation as a character string. +#' @param output.type character One of "expression", "latex", "tex", "text", +#' "tikz", "markdown". +#' +#' @note exponential number notation to typeset equivalent: Protecting trailing +#' zeros in negative numbers is more involved than I would like. Not only we +#' need to enclose numbers in quotations marks but we also need to replace +#' dashes with the minus character. I am not sure we can do the replacement +#' portably, but that recent R supports UTF gives some hope. +#' +#' @return A \code{character} string. +#' +typeset_numbers <- function(eq.char, output.type) { + if (output.type == "markdown") { + eq.char <- gsub("e([+-]?)[0]([1-9]*)", "×10\\1\\2", eq.char) + eq.char <- gsub("[:^]([0-9]*)", "\\1", eq.char) + eq.char <- gsub("*", " ", eq.char, fixed = TRUE) + eq.char <- gsub(" ", "", eq.char, fixed = TRUE) + } else { + eq.char <- gsub("e([+-]?[0-9]*)", "%*% 10^{\\1}", eq.char) + # muliplication symbol + if (output.type %in% c("latex", "tikz")) { + eq.char <- gsub("%*%", "\\times{}", eq.char, fixed = TRUE) + eq.char <- gsub("*", "", eq.char, fixed = TRUE) + } else if (output.type == "text") { + eq.char <- gsub("[{]|[}]", "", eq.char, fixed = FALSE) + eq.char <- gsub("%*%", "", eq.char, fixed = TRUE) + eq.char <- gsub("*", " ", eq.char, fixed = TRUE) + eq.char <- gsub(" ", " ", eq.char, fixed = TRUE) + } + } + eq.char +} + +#' Format a polynomial as an equation +#' +#' Uses a vector of coefficients from a model fit of a polynomial to build +#' the fitted model equation with embedded coefficient estimates. +#' +#' @param coefs numeric Terms always sorted by increasing powers. +#' @param coef.digits integer +#' @param coef.keep.zeros logical This flag refers to trailing zeros. +#' @param decreasing logical It specifies the order of the terms in the +#' returned character string; in increasing (default) or decreasing powers. +#' @param eq.x.rhs character +#' @param lhs character +#' @param output.type character One of "expression", "latex", "tex", "text", +#' "tikz", "markdown". +#' @param decimal.mark character +#' +#' @note Terms with zero-valued coefficients are dropped from the polynomial. +#' +#' @return A \code{character} string. +#' +#' @examples +#' coefs2poly_eq(c(1, 2, 0, 4, 5, 2e-5)) +#' coefs2poly_eq(c(1, 2, 0, 4, 5, 2e-5), output.type = "latex") +#' coefs2poly_eq(0:2) +#' coefs2poly_eq(0:2, decreasing = TRUE) +#' coefs2poly_eq(c(1, 2, 0, 4, 5), coef.keep.zeros = TRUE) +#' coefs2poly_eq(c(1, 2, 0, 4, 5), coef.keep.zeros = FALSE) +#' +#' @export +#' +coefs2poly_eq <- function(coefs, + coef.digits = 3L, + coef.keep.zeros = TRUE, + decreasing = FALSE, + eq.x.rhs = "x", + lhs = "y~`=`~", + output.type = "expression", + decimal.mark = ".") { + # build equation as a character string from the coefficient estimates + stopifnot(coef.digits > 0) + if (coef.digits < 3) { + warning("'coef.digits < 3' Likely information loss!") + } + eq.char <- poly2character(polynom::as.polynomial(coefs), + decreasing = decreasing, + digits = coef.digits, + keep.zeros = coef.keep.zeros) + eq.char <- typeset_numbers(eq.char, output.type) + if (output.type != "expression") { # parse() does the conversion + if (decimal.mark == ".") { + eq.char <- gsub(",", decimal.mark, eq.char, fixed = TRUE) + } else { + eq.char <- gsub(".", decimal.mark, eq.char, fixed = TRUE) + } + } + + if (eq.x.rhs != "x") { + eq.char <- gsub("x", eq.x.rhs, eq.char, fixed = TRUE) + } + if (length(lhs)) { + eq.char <- paste(lhs, eq.char, sep = "") + } + + eq.char +} + diff --git a/R/utilities-labels.R b/R/utilities-labels.R new file mode 100644 index 0000000..6edfa05 --- /dev/null +++ b/R/utilities-labels.R @@ -0,0 +1,931 @@ +#' Format numeric values as strings +#' +#' Using \code{\link{sprintf}} flexibly format numbers as character strings +#' encoded for parsing into R expressions or using \eqn{\LaTeX} or markdown +#' notation. +#' +#' @param fmt character as in \code{sprintf()}. +#' @param ... as in \code{sprintf()}. +#' @param decimal.mark character If \code{NULL} or \code{NA} no substitution is +#' attempted and the value returned by \code{sprintf()} is returned as is. +#' +#' @details These functions are used to format the character strings returned, +#' which can be used as labels in plots. Encoding used for the formatting is +#' selected by the argument passed to \code{output.type}, thus, supporting +#' different R graphic devices. +#' +#' @seealso \code{\link[base]{sprintf}} +#' +#' @examples +#' +#' sprintf_dm("%2.3f", 2.34) +#' sprintf_dm("%2.3f", 2.34, decimal.mark = ",") +#' +#' @export +#' +sprintf_dm <- function(fmt, + ..., + decimal.mark = getOption("OutDec", default = ".")) { + if (is.null(decimal.mark) || is.na(decimal.mark)) { + sprintf(fmt, ...) + } else if (decimal.mark != ".") { + gsub(".", decimal.mark, sprintf(fmt, ...), fixed = TRUE) + } else { + # in case OS locale uses "," + gsub(",", ".", sprintf(fmt, ...), fixed = TRUE) + } +} + +#' @rdname sprintf_dm +#' +#' @param value numeric The value of the estimate. +#' @param digits integer Number of digits to which numeric values are formatetd. +#' @param fixed logical Interpret \code{digits} as indicating a number of +#' digits after the decimal mark or as the number of significant digits. +#' @param output.type character One of "expression", "latex", "tex", "text", +#' "tikz", "markdown". +#' +#' @examples +#' +#' value2char(2.34) +#' value2char(2.34, digits = 3, fixed = FALSE) +#' value2char(2.34, digits = 3, fixed = TRUE) +#' value2char(2.34, output.type = "text") +#' +#' @export +#' +value2char <- function(value, + digits = Inf, + fixed = FALSE, + output.type = "expression", + decimal.mark = getOption("OutDec", default = ".")) { + if (output.type == "expression") { + if (digits == Inf) { + temp.char <- sprintf_dm("\"%#.2e\"", value, decimal.mark = decimal.mark) + } else { + temp.char <- sprintf_dm(ifelse(fixed, "\"%#.*f\"", "\"%#.*g\""), + digits, value, decimal.mark = decimal.mark) + } + if (grepl("e", temp.char)) { + # dash -> minus + paste(gsub("e", "\" %*% 10^{\"", gsub("-", "\u2212", temp.char)), "}", sep = "") + } else { + temp.char + } + } else { + if (digits == Inf) { + temp.char <- sprintf_dm("%#.2e", value, decimal.mark = decimal.mark) + } else { + temp.char <- sprintf_dm(ifelse(fixed, "%#.*f", "%#.*g"), + digits, value, decimal.mark = decimal.mark) + } + if (output.type %in% c("latex", "tex", "tikz") && grepl("e", temp.char)) { + paste(gsub("e", " \times 10^{", temp.char), "}", sep = "") + } else { + temp.char + } + } +} + +#' Format numbers as character labels +#' +#' These functions format numeric values as character labels including the +#' symbol for statistical parameter estimates suitable for adding to plots. The +#' labels can be formatted as strings to be parsed as plotmath expressions, +#' or encoded using LaTeX or Markdown. +#' +#' @param value numeric The value of the estimate. +#' @param value.name character The symbol used to represent the value, or its +#' name. +#' @param df,df1,df2 numeric The degrees of freedom of the estimate. +#' @param small.p,small.r logical If \code{TRUE} use lower case (\eqn{p} and +#' \eqn{r}, \eqn{r^2}) instead of upper case (\eqn{P} and +#' \eqn{R}, \eqn{R^2}), +#' @param digits integer Number of digits to which numeric values are formatetd. +#' @param fixed logical Interpret \code{digits} as indicating a number of +#' digits after the decimal mark or as the number of significant digits. +#' @param output.type character One of "expression", "latex", "tex", "text", +#' "tikz", "markdown". +#' @param decimal.mark character Defaults to the value of R option +#' \code{"OutDec"}. +#' +#' @return A character string with formatting, encoded to be parsed as an R +#' plotmath expression, as plain text, as markdown or to be used with +#' \eqn{LaTeX} within \strong{math mode}. +#' +#' @seealso \code{\link{sprintf_dm}} +#' +#' @export +#' +#' @examples +#' plain_label(value = 123, value.name = "n", output.type = "expression") +#' plain_label(value = 123, value.name = "n", output.type = "markdown") +#' plain_label(value = 123, value.name = "n", output.type = "latex") +#' italic_label(value = 123, value.name = "n", output.type = "expression") +#' italic_label(value = 123, value.name = "n", output.type = "markdown") +#' italic_label(value = 123, value.name = "n", output.type = "latex") +#' bold_label(value = 123, value.name = "n", output.type = "expression") +#' bold_label(value = 123, value.name = "n", output.type = "markdown") +#' bold_label(value = 123, value.name = "n", output.type = "latex") +#' +plain_label <- function(value, + value.name, + digits = 3, + fixed = FALSE, + output.type = "expression", + decimal.mark = getOption("OutDec", default = ".")) { + + stopifnot(length(value) == 1L) + + if (is.na(value) || is.nan(value)) { + return(NA_character_) + } + + if (is.integer(value)) { + value.char <- as.character(value) + } else { + value.char <- value2char(value = value, + digits = digits, + output.type = output.type, + decimal.mark = decimal.mark, + fixed = fixed) + } + + if (output.type == "expression") { + paste("plain(", value.name, ")~`=`~", value.char, sep = "") + } else if (output.type %in% c("latex", "tex", "tikz")) { + paste("\\mathrm{", value.name, "} = ", value.char, sep = "") + } else if (output.type %in% c("text", "markdown")) { + paste(value.name, " = ", value.char, sep = "") + } +} + +#' @rdname plain_label +#' +#' @export +#' +italic_label <- function(value, + value.name, + digits = 3, + fixed = FALSE, + output.type = "expression", + decimal.mark = getOption("OutDec", default = ".")) { + + stopifnot(length(value) == 1L) + + if (is.na(value) || is.nan(value)) { + return(NA_character_) + } + + if (is.integer(value)) { + value.char <- as.character(value) + } else { + value.char <- value2char(value = value, + digits = digits, + output.type = output.type, + decimal.mark = decimal.mark, + fixed = fixed) + } + + if (output.type == "expression") { + paste("italic(", value.name, ")~`=`~", value.char, sep = "") + } else if (output.type %in% c("latex", "tex", "tikz")) { + paste("\\mathit{", value.name, "} = ", value.char, sep = "") + } else if (output.type %in% c("text", "markdown")) { + paste("_", value.name, "_ = ", value.char, sep = "") + } +} + +#' @rdname plain_label +#' +#' @export +#' +bold_label <- function(value, + value.name, + digits = 3, + fixed = FALSE, + output.type = "expression", + decimal.mark = getOption("OutDec", default = ".")) { + + stopifnot(length(value) == 1L) + + if (is.na(value) || is.nan(value)) { + return(NA_character_) + } + + if (is.integer(value)) { + value.char <- as.character(value) + } else { + value.char <- value2char(value = value, + digits = digits, + output.type = output.type, + decimal.mark = decimal.mark, + fixed = fixed) + } + + if (output.type == "expression") { + paste("bold(", value.name, ")~`=`~", value.char, sep = "") + } else if (output.type %in% c("latex", "tex", "tikz")) { + paste("\\mathbf{", value.name, "} = ", value.char, sep = "") + } else if (output.type %in% c("text", "markdown")) { + paste("**", value.name, "** = ", value.char, sep = "") + } +} + +#' @rdname plain_label +#' +#' @param subscript,superscript character Text for a subscript and superscript +#' to \emph{P} symbol. +#' +#' @examples +#' p_value_label(value = 0.345, digits = 2, output.type = "expression") +#' p_value_label(value = 0.345, digits = Inf, output.type = "expression") +#' p_value_label(value = 0.345, digits = 6, output.type = "expression") +#' p_value_label(value = 0.345, output.type = "markdown") +#' p_value_label(value = 0.345, output.type = "latex") +#' p_value_label(value = 0.345, subscript = "Holm") +#' p_value_label(value = 1e-25, digits = Inf, output.type = "expression") +#' +#' @export +#' +p_value_label <- function(value, + small.p = FALSE, + subscript = "", + superscript = "", + digits = 4, + fixed = TRUE, + output.type = "expression", + decimal.mark = getOption("OutDec", default = ".")) { + + stopifnot(length(value) <= 1L, + "Negative value of 'digits'" = digits > 0) + + if (length(value) == 0 || is.na(value) || is.nan(value)) { + return(NA_character_) + } + + if (value < 0 && value > -1e-12) { + value <- 0 + } else if (value > 1 && value < 1 + 1e-12) { + value <- 1 + } else if (value < 0 || value > 1) { + warning("Out of range P-value replaced by 'NA'") + value <- NA_real_ + } + + if (digits < 2) { + warning("'digits < 2' Likely information loss!") + } + p.value <- value + + if (is.na(subscript) | !is.character(subscript) | length(subscript) != 1L) { + subscript <- "" + } + + p.value.char <- value2char(value = p.value, + digits = digits, + output.type = output.type, + decimal.mark = decimal.mark, + fixed = fixed) + + if (output.type == "expression") { + paste(paste(ifelse(small.p, "italic(p)", "italic(P)"), + ifelse(subscript != "", + paste("[", subscript, "]", sep = ""), + ""), + ifelse(superscript != "", + paste("^{", superscript, "}", sep = ""), + ""), + sep = ""), + ifelse(p.value < 10^(-digits), + sprintf_dm("\"%.*f\"", digits, 10^(-digits), + decimal.mark = decimal.mark), + p.value.char), + sep = ifelse(p.value < 10^(-digits), + "~`<`~", + "~`=`~")) + } else if (output.type %in% c("latex", "tex", "text", "tikz")) { + paste(paste(ifelse(small.p, "p", "P"), + ifelse(subscript != "", + paste("_{", subscript, "}", sep = ""), + ""), + ifelse(superscript != "", + paste("^{", superscript, "}", sep = ""), + ""), + sep = ""), + ifelse(p.value < 10^(-digits), + sprintf_dm("\"%.*f\"", digits, 10^(-digits), + decimal.mark = decimal.mark), + p.value.char), + sep = ifelse(p.value < 10^(-digits), + " < ", + " = ")) + } else if (output.type == "markdown") { + paste(paste(ifelse(small.p, "_p_", "_P_"), + ifelse(subscript != "", + paste("", subscript, "", sep = ""), + character()), + ifelse(superscript != "", + paste("", superscript, "", sep = ""), + character()), + sep = ""), + ifelse(p.value < 10^(-digits), + sprintf_dm("\"%.*f\"", digits, 10^(-digits), + decimal.mark = decimal.mark), + p.value.char), + sep = ifelse(p.value < 10^(-digits), + " < ", + " = ")) + } +} + +#' @rdname plain_label +#' +#' @examples +#' f_value_label(value = 123.4567, digits = 2, output.type = "expression") +#' f_value_label(value = 123.4567, digits = Inf, output.type = "expression") +#' f_value_label(value = 123.4567, digits = 6, output.type = "expression") +#' f_value_label(value = 123.4567, output.type = "markdown") +#' f_value_label(value = 123.4567, output.type = "latex") +#' f_value_label(value = 123.4567, df1 = 3, df2 = 123, +#' digits = 2, output.type = "expression") +#' f_value_label(value = 123.4567, df1 = 3, df2 = 123, +#' digits = 2, output.type = "latex") +#' +#' @export +#' +f_value_label <- function(value, + df1 = NULL, + df2 = NULL, + digits = 4, + fixed = FALSE, + output.type = "expression", + decimal.mark = getOption("OutDec", default = ".")) { + + stopifnot(length(value) == 1L, + "Out of range F-value" = is.na(value) | value >= 0) + f.value <- value + + if (is.na(f.value) || is.nan(f.value)) { + return(NA_character_) + } + + if (is.null(df1) || is.null(df2)) { + return(italic_label(value = f.value, + value.name = "F", + digits = digits, + fixed = fixed, + output.type = output.type, + decimal.mark = decimal.mark) + ) + } + + f.value.char <- value2char(value = f.value, + digits = digits, + output.type = output.type, + decimal.mark = decimal.mark, + fixed = fixed) + + df1.char <- as.character(df1) + df2.char <- as.character(df2) + + if (output.type == "expression") { + paste("italic(F)[", df1.char, + "*\",\"*", df2.char, + "]~`=`~", f.value.char, sep = "") + } else if (output.type %in% c("latex", "tex", "text", "tikz")) { + paste("F_{", df1.char, ",", df2.char, + "} = ", f.value.char, sep = "") + } else if (output.type == "markdown") { + paste("_F_", df1.char, ",", df2.char, + " = ", f.value.char, sep = "") + } +} + +#' @rdname plain_label +#' +#' @examples +#' t_value_label(value = 123.4567, digits = 2, output.type = "expression") +#' t_value_label(value = 123.4567, digits = Inf, output.type = "expression") +#' t_value_label(value = 123.4567, digits = 6, output.type = "expression") +#' t_value_label(value = 123.4567, output.type = "markdown") +#' t_value_label(value = 123.4567, output.type = "latex") +#' t_value_label(value = 123.4567, df = 12, +#' digits = 2, output.type = "expression") +#' t_value_label(value = 123.4567, df = 123, +#' digits = 2, output.type = "latex") +#' +#' @export +#' +t_value_label <- function(value, + df = NULL, + digits = 4, + fixed = FALSE, + output.type = "expression", + decimal.mark = getOption("OutDec", default = ".")) { + + stopifnot(length(value) == 1L) + t.value <- value + + if (is.na(t.value) || is.nan(t.value)) { + return(NA_character_) + } + + if (is.null(df)) { + return(italic_label(value = t.value, + value.name = "t", + digits = digits, + fixed = fixed, + output.type = output.type, + decimal.mark = decimal.mark) + ) + } + + t.value.char <- value2char(value = t.value, + digits = digits, + output.type = output.type, + decimal.mark = decimal.mark, + fixed = fixed) + df.char <- as.character(df) + + if (output.type == "expression") { + paste("italic(t)[", df.char, + "]~`=`~", t.value.char, sep = "") + } else if (output.type %in% c("latex", "tex", "text", "tikz")) { + paste("t_{", df.char, + "} = ", t.value.char, sep = "") + } else if (output.type == "markdown") { + paste("_t_", df.char, + " = ", t.value.char, sep = "") + } +} + +z_value_label <- function(value, + digits = 4, + fixed = FALSE, + output.type = "expression", + decimal.mark = getOption("OutDec", default = ".")) { + + italic_label(value = value, + value.name = "z", + digits = digits, + fixed = fixed, + output.type = output.type, + decimal.mark = decimal.mark) +} + +S_value_label <- function(value, + digits = 4, + fixed = FALSE, + output.type = "expression", + decimal.mark = getOption("OutDec", default = ".")) { + + italic_label(value = value, + value.name = "S", + digits = digits, + fixed = fixed, + output.type = output.type, + decimal.mark = decimal.mark) +} + +mean_value_label <- function(value, + digits = 4, + fixed = FALSE, + output.type = "expression", + decimal.mark = getOption("OutDec", default = ".")) { + + value.name <- if (output.type == "expression") { + "bar(x)" + } else if (output.type %in% c("latex", "tex", "tikz")) { + "\\bar{x}" + } else if (output.type == "markdown") { + "mean(x)" + } else { + "mean(x)" + } + + italic_label(value = value, + value.name = value.name, + digits = digits, + fixed = fixed, + output.type = output.type, + decimal.mark = decimal.mark) +} + +var_value_label <- function(value, + digits = 4, + fixed = FALSE, + output.type = "expression", + decimal.mark = getOption("OutDec", default = ".")) { + value.name <- if (output.type == "expression") { + "sigma^2" + } else if (output.type %in% c("latex", "tex", "tikz")) { + "\\sigma^2" + } else if (output.type == "markdown") { + "σ2" + } else { + "s^2" + } + + italic_label(value = value, + value.name = value.name, + digits = digits, + fixed = fixed, + output.type = output.type, + decimal.mark = decimal.mark) +} + +sd_value_label <- function(value, + digits = 4, + fixed = FALSE, + output.type = "expression", + decimal.mark = getOption("OutDec", default = ".")) { + value.name <- if (output.type == "expression") { + "sigma" + } else if (output.type %in% c("latex", "tex", "tikz")) { + "\\sigma" + } else if (output.type == "markdown") { + "σ" + } else { + "s.d." + } + + italic_label(value = value, + value.name = value.name, + digits = digits, + fixed = fixed, + output.type = output.type, + decimal.mark = decimal.mark) +} + +se_value_label <- function(value, + digits = 4, + fixed = FALSE, + output.type = "expression", + decimal.mark = getOption("OutDec", default = ".")) { + + italic_label(value = value, + value.name = "s.e.", + digits = digits, + fixed = fixed, + output.type = output.type, + decimal.mark = decimal.mark) +} + +#' @rdname plain_label +#' +#' @param method character The method used to estimate correlation, which +#' selects the symbol used for the value. +#' +#' @examples +#' r_label(value = 0.95, digits = 2, output.type = "expression") +#' r_label(value = -0.95, digits = 2, output.type = "expression") +#' r_label(value = 0.0001, digits = 2, output.type = "expression") +#' r_label(value = -0.0001, digits = 2, output.type = "expression") +#' r_label(value = 0.1234567890, digits = Inf, output.type = "expression") +#' r_label(value = 0.95, digits = 2, method = "pearson") +#' r_label(value = 0.95, digits = 2, method = "kendall") +#' r_label(value = 0.95, digits = 2, method = "spearman") +#' +#' @export +#' +r_label <- function(value, + method = "pearson", + small.r = FALSE, + digits = 3, + fixed = TRUE, + output.type = "expression", + decimal.mark = getOption("OutDec", default = ".")) { + + if (method == "pearson") { + stopifnot(length(value) == 1L, + "Out of range R" = is.na(value) || abs(value) <= 1, + "Negative value of 'digits'" = digits > 0) + } else { + stopifnot(length(value) == 1L, + "Negative value of 'digits'" = digits > 0) + } + + if (digits < 2) { + warning("'digits < 2' Likely information loss!") + } + r.value <- value + + if (is.na(r.value) || is.nan(r.value)) { + return(NA_character_) + } + + r.value.char <- value2char(value = r.value, + digits = digits, + output.type = output.type, + decimal.mark = decimal.mark, + fixed = fixed) + + if (output.type == "expression") { + + r.symbol <- + if (method == "pearson") { + ifelse(small.r, "italic(r)", "italic(R)") + } else if (method == "kendall") { + "italic(tau)" + } else if (method == "spearman") { + "italic(rho)" + } else { + character(0) + } + + if (abs(r.value) < 10^(-digits) & r.value != 0) { + paste("|", r.symbol, "|", "~ < ~", + sprintf_dm("\"%.*f\"", digits, 10^(-digits), decimal.mark = decimal.mark), + sep = "") + } else { + paste(r.symbol, "~`=`~", r.value.char) + } + + } else if (output.type %in% c("latex", "tex", "text", "tikz")) { + + r.symbol <- + if (method == "pearson") { + ifelse(small.r, "r", "R") + } else if (method == "kendall") { + ifelse(output.type == "text", "tau", "\tau") + } else if (method == "spearman") { + ifelse(output.type == "text", "rho", "\rho") + } else { + character(0) + } + + if (abs(r.value) < 10^(-digits) & r.value != 0) { + paste("|", r.symbol, "|", " < ", + sprintf_dm("%.*f", digits, 10^(-digits), decimal.mark = decimal.mark), + sep = "") + } else { + paste(r.symbol, " = ", r.value.char) + } + + } else if (output.type == "markdown") { + + r.symbol <- + if (method == "pearson") { + ifelse(small.r, "_r_", "_R_") + } else if (method == "kendall") { + "_ρ_" + } else if (method == "spearman") { + "_τ_" + } else { + character(0) + } + + if (abs(r.value) < 10^(-digits) & r.value != 0) { + paste("|", r.symbol, "|", " < ", + sprintf_dm("%.*f", digits, 10^(-digits), decimal.mark = decimal.mark), + sep = "") + } else { + paste(r.symbol, " = ", r.value.char) + } + + } +} + +#' @rdname plain_label +#' +#' @examples +#' rr_label(value = 0.95, digits = 2, output.type = "expression") +#' rr_label(value = 0.0001, digits = 2, output.type = "expression") +#' +#' @export +#' +rr_label <- function(value, + small.r = FALSE, + digits = 3, + fixed = TRUE, + output.type = "expression", + decimal.mark = getOption("OutDec", default = ".")) { + + stopifnot(length(value) == 1L, + "Out of range R^2" = is.na(value) | (value >= 0 & value <= 1), + "Negative value of 'digits'" = digits > 0) + if (digits < 2) { + warning("'digits < 2' Likely information loss!") + } + rr.value <- value + + if (is.na(rr.value) || is.nan(rr.value)) { + return(NA_character_) + } + + rr.value.char <- value2char(value = rr.value, + digits = digits, + output.type = output.type, + decimal.mark = decimal.mark, + fixed = fixed) + + if (output.type == "expression") { + rr.symbol <- ifelse(small.r, "italic(r)^2", "italic(R)^2") + if (rr.value < 10^(-digits) & rr.value != 0) { + paste(rr.symbol, + sprintf_dm("\"%.*f\"", digits, 10^(-digits), decimal.mark = decimal.mark), + sep = "~`<`~") + } else { + paste(rr.symbol, rr.value.char, sep = "~`=`~") + } + } else if (output.type %in% c("latex", "tex", "text", "tikz")) { + rr.symbol <- ifelse(small.r, "r^2", "R^2") + if (rr.value < 10^(-digits) & rr.value != 0) { + paste(rr.symbol, + sprintf_dm("%.*f", digits, 10^(-digits), decimal.mark = decimal.mark), + sep = " < ") + } else { + paste(rr.symbol, rr.value.char, sep = " = ") + } + } else if (output.type == "markdown") { + rr.symbol <- ifelse(small.r, "_r_2", "_R_2") + if (rr.value < 10^(-digits) & rr.value != 0) { + paste(rr.symbol, + as.character(10^(-digits)), + sep = " < ") + } else { + paste(rr.symbol, rr.value.char, sep = " = ") + } + } +} + +#' @rdname plain_label +#' +#' @examples +#' adj_rr_label(value = 0.95, digits = 2, output.type = "expression") +#' adj_rr_label(value = 0.0001, digits = 2, output.type = "expression") +#' +#' @export +#' +adj_rr_label <- function(value, + small.r = FALSE, + digits = 3, + fixed = TRUE, + output.type = "expression", + decimal.mark = getOption("OutDec", default = ".")) { + + stopifnot(length(value) == 1L, + "Negative value of 'digits'" = digits > 0) + if (digits < 2) { + warning("'digits < 2' Likely information loss!") + } + adj.rr.value <- value + + if (is.na(adj.rr.value) || is.nan(adj.rr.value)) { + return(NA_character_) + } + + adj.rr.value.char <- value2char(value = adj.rr.value, + digits = digits, + output.type = output.type, + decimal.mark = decimal.mark, + fixed = fixed) + + if (output.type == "expression") { + paste(ifelse(small.r, "italic(r)[adj]^2", "italic(R)[adj]^2"), + ifelse(adj.rr.value < 10^(-digits) & adj.rr.value != 0, + sprintf_dm("\"%.*f\"", digits, 10^(-digits), decimal.mark = decimal.mark), + adj.rr.value.char), + sep = ifelse(adj.rr.value < 10^(-digits) & adj.rr.value != 0, + "~`<`~", + "~`=`~")) + } else if (output.type %in% c("latex", "tex", "text", "tikz")) { + paste(ifelse(small.r, "r_{adj}^2", "R_{adj}^2"), + ifelse(adj.rr.value < 10^(-digits), as.character(10^(-digits)), adj.rr.value.char), + sep = ifelse(adj.rr.value < 10^(-digits), " < ", " = ")) + } else if (output.type == "markdown") { + paste(ifelse(small.r, "_r_2adj", "_R_2adj"), + ifelse(adj.rr.value < 10^(-digits), as.character(10^(-digits)), adj.rr.value.char), + sep = ifelse(adj.rr.value < 10^(-digits), " < ", " = ")) + } +} + +#' @rdname plain_label +#' +#' @param conf.level numeric critical \emph{P}-value expressed as fraction in +#' [0..1]. +#' @param range.brackets,range.sep character Strings used to format a range. +#' +#' @examples +#' rr_ci_label(value = c(0.3, 0.4), conf.level = 0.95) +#' rr_ci_label(value = c(0.3, 0.4), conf.level = 0.95, output.type = "text") +#' rr_ci_label(value = c(0.3, 0.4), conf.level = 0.95, range.sep = ",") +#' +#' @export +#' +rr_ci_label <- function(value, + conf.level, + range.brackets = c("[", "]"), + range.sep = NULL, + digits = 2, + fixed = TRUE, + output.type = "expression", + decimal.mark = getOption("OutDec", default = ".")) { + + stopifnot(length(value) == 2L, + "Out of range R^2-value" = all(is.na(value) | (value >= 0 & value <= 1)), + "Negative value of 'digits'" = digits > 0) + if (digits < 2) { + warning("'digits < 2' Likely information loss!") + } + rr.ci.value <- sort(value) + + if (is.null(range.sep)) { + range.sep <- c("." = ", ", "," = "; ")[decimal.mark] + } + + if (any(is.na(rr.ci.value) | is.nan(rr.ci.value))) { + return(NA_character_) + } + + rr.ci.char <- character(2) + rr.ci.char[1] <- value2char(value = rr.ci.value[1], + digits = digits, + output.type = "text", + decimal.mark = decimal.mark, + fixed = fixed) + rr.ci.char[2] <- value2char(value = rr.ci.value[2], + digits = digits, + output.type = "text", + decimal.mark = decimal.mark, + fixed = TRUE) + rr.ci.char <- paste(rr.ci.char[1], rr.ci.char[2], sep = range.sep) + if (as.logical((conf.level * 100) %% 1)) { + conf.level.digits = 1L + } else { + conf.level.digits = 0L + } + conf.level.char <- as.character(conf.level * 100) + + if (output.type == "expression") { + paste("\"", conf.level.char, "% CI ", + range.brackets[1], rr.ci.char, range.brackets[2], "\"", sep = "") + } else if (output.type %in% c("latex", "tex", "text", "tikz", "markdown")) { + paste(conf.level.char, "% CI ", + range.brackets[1], rr.ci.char, range.brackets[2], sep = "") + } +} + +#' @rdname plain_label +#' +#' @examples +#' r_ci_label(value = c(-0.3, 0.4), conf.level = 0.95) +#' r_ci_label(value = c(-0.3, 0.4), conf.level = 0.95, output.type = "text") +#' r_ci_label(value = c(-0.3, 0.4), conf.level = 0.95, range.sep = ",") +#' +#' @export +#' +r_ci_label <- function(value, + conf.level, + small.r = FALSE, + range.brackets = c("[", "]"), + range.sep = NULL, + digits = 2, + fixed = TRUE, + output.type = "expression", + decimal.mark = getOption("OutDec", default = ".")) { + + stopifnot(length(value) == 2L, + "Out of range R-value" = all(is.na(value) | (value >= -1 & value <= 1)), + "Negative value of 'digits'" = digits > 0) + if (digits < 2) { + warning("'digits < 2' Likely information loss!") + } + r.ci.value <- sort(value) + + if (is.null(range.sep)) { + range.sep <- c("." = ", ", "," = "; ")[decimal.mark] + } + + if (any(is.na(r.ci.value) | is.nan(r.ci.value))) { + return(NA_character_) + } + + r.ci.char <- character(2) + r.ci.char[1] <- value2char(value = r.ci.value[1], + digits = digits, + output.type = "text", + decimal.mark = decimal.mark, + fixed = fixed) + r.ci.char[2] <- value2char(value = r.ci.value[2], + digits = digits, + output.type = "text", + decimal.mark = decimal.mark, + fixed = TRUE) + r.ci.char <- paste(r.ci.char[1], r.ci.char[2], sep = range.sep) + if (as.logical((conf.level * 100) %% 1)) { + conf.level.digits = 1L + } else { + conf.level.digits = 0L + } + conf.level.char <- as.character(conf.level * 100) + + if (output.type == "expression") { + paste("\"", conf.level.char, "% CI ", + range.brackets[1], r.ci.char, range.brackets[2], "\"", sep = "") + } else if (output.type %in% c("latex", "tex", "text", "tikz", "markdown")) { + paste(conf.level.char, "% CI ", + range.brackets[1], r.ci.char, range.brackets[2], sep = "") + } +} diff --git a/_pkgdown.yml b/_pkgdown.yml index b435189..a92ba24 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -44,6 +44,11 @@ reference: - title: Utilities desc: Low level functions used to build some of the functions above, but possibly useful also in other contexts. contents: + - sprintf_dm + - plain_label + - coefs2poly_eq + - poly2character + - typeset_numbers - find_peaks - coef.lmodel2 - confint.lmodel2 diff --git a/man/build_eq.x.rhs.Rd b/man/build_eq.x.rhs.Rd new file mode 100644 index 0000000..4d86180 --- /dev/null +++ b/man/build_eq.x.rhs.Rd @@ -0,0 +1,27 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utilities-eq-label.R +\name{build_eq.x.rhs} +\alias{build_eq.x.rhs} +\alias{build_lhs} +\title{Left and right hand sides of model equations} +\usage{ +build_eq.x.rhs(output.type = "expression", orientation = "x") + +build_lhs(output.type = "expression", orientation = "x") +} +\arguments{ +\item{output.type}{character One of "expression", "latex", "tex", "text", +"tikz", "markdown".} + +\item{orientation}{character \code{"x"} or \code{"y"}, indicating +the aesthetic onto which the explanatory variable is mapped.} +} +\value{ +A \code{character} string. + +A \code{character} string. +} +\description{ +Left and right hand sides of model equations +} +\keyword{internal} diff --git a/man/coefs2poly_eq.Rd b/man/coefs2poly_eq.Rd new file mode 100644 index 0000000..919ba9c --- /dev/null +++ b/man/coefs2poly_eq.Rd @@ -0,0 +1,55 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utilities-eq-label.R +\name{coefs2poly_eq} +\alias{coefs2poly_eq} +\title{Format a polynomial as an equation} +\usage{ +coefs2poly_eq( + coefs, + coef.digits = 3L, + coef.keep.zeros = TRUE, + decreasing = FALSE, + eq.x.rhs = "x", + lhs = "y~`=`~", + output.type = "expression", + decimal.mark = "." +) +} +\arguments{ +\item{coefs}{numeric Terms always sorted by increasing powers.} + +\item{coef.digits}{integer} + +\item{coef.keep.zeros}{logical This flag refers to trailing zeros.} + +\item{decreasing}{logical It specifies the order of the terms in the +returned character string; in increasing (default) or decreasing powers.} + +\item{eq.x.rhs}{character} + +\item{lhs}{character} + +\item{output.type}{character One of "expression", "latex", "tex", "text", +"tikz", "markdown".} + +\item{decimal.mark}{character} +} +\value{ +A \code{character} string. +} +\description{ +Uses a vector of coefficients from a model fit of a polynomial to build +the fitted model equation with embedded coefficient estimates. +} +\note{ +Terms with zero-valued coefficients are dropped from the polynomial. +} +\examples{ +coefs2poly_eq(c(1, 2, 0, 4, 5, 2e-5)) +coefs2poly_eq(c(1, 2, 0, 4, 5, 2e-5), output.type = "latex") +coefs2poly_eq(0:2) +coefs2poly_eq(0:2, decreasing = TRUE) +coefs2poly_eq(c(1, 2, 0, 4, 5), coef.keep.zeros = TRUE) +coefs2poly_eq(c(1, 2, 0, 4, 5), coef.keep.zeros = FALSE) + +} diff --git a/man/plain_label.Rd b/man/plain_label.Rd new file mode 100644 index 0000000..c099894 --- /dev/null +++ b/man/plain_label.Rd @@ -0,0 +1,235 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utilities-labels.R +\name{plain_label} +\alias{plain_label} +\alias{italic_label} +\alias{bold_label} +\alias{p_value_label} +\alias{f_value_label} +\alias{t_value_label} +\alias{r_label} +\alias{rr_label} +\alias{adj_rr_label} +\alias{rr_ci_label} +\alias{r_ci_label} +\title{Format numbers as character labels} +\usage{ +plain_label( + value, + value.name, + digits = 3, + fixed = FALSE, + output.type = "expression", + decimal.mark = getOption("OutDec", default = ".") +) + +italic_label( + value, + value.name, + digits = 3, + fixed = FALSE, + output.type = "expression", + decimal.mark = getOption("OutDec", default = ".") +) + +bold_label( + value, + value.name, + digits = 3, + fixed = FALSE, + output.type = "expression", + decimal.mark = getOption("OutDec", default = ".") +) + +p_value_label( + value, + small.p = FALSE, + subscript = "", + superscript = "", + digits = 4, + fixed = TRUE, + output.type = "expression", + decimal.mark = getOption("OutDec", default = ".") +) + +f_value_label( + value, + df1 = NULL, + df2 = NULL, + digits = 4, + fixed = FALSE, + output.type = "expression", + decimal.mark = getOption("OutDec", default = ".") +) + +t_value_label( + value, + df = NULL, + digits = 4, + fixed = FALSE, + output.type = "expression", + decimal.mark = getOption("OutDec", default = ".") +) + +r_label( + value, + method = "pearson", + small.r = FALSE, + digits = 3, + fixed = TRUE, + output.type = "expression", + decimal.mark = getOption("OutDec", default = ".") +) + +rr_label( + value, + small.r = FALSE, + digits = 3, + fixed = TRUE, + output.type = "expression", + decimal.mark = getOption("OutDec", default = ".") +) + +adj_rr_label( + value, + small.r = FALSE, + digits = 3, + fixed = TRUE, + output.type = "expression", + decimal.mark = getOption("OutDec", default = ".") +) + +rr_ci_label( + value, + conf.level, + range.brackets = c("[", "]"), + range.sep = NULL, + digits = 2, + fixed = TRUE, + output.type = "expression", + decimal.mark = getOption("OutDec", default = ".") +) + +r_ci_label( + value, + conf.level, + small.r = FALSE, + range.brackets = c("[", "]"), + range.sep = NULL, + digits = 2, + fixed = TRUE, + output.type = "expression", + decimal.mark = getOption("OutDec", default = ".") +) +} +\arguments{ +\item{value}{numeric The value of the estimate.} + +\item{value.name}{character The symbol used to represent the value, or its +name.} + +\item{digits}{integer Number of digits to which numeric values are formatetd.} + +\item{fixed}{logical Interpret \code{digits} as indicating a number of +digits after the decimal mark or as the number of significant digits.} + +\item{output.type}{character One of "expression", "latex", "tex", "text", +"tikz", "markdown".} + +\item{decimal.mark}{character Defaults to the value of R option +\code{"OutDec"}.} + +\item{small.p, small.r}{logical If \code{TRUE} use lower case (\eqn{p} and +\eqn{r}, \eqn{r^2}) instead of upper case (\eqn{P} and +\eqn{R}, \eqn{R^2}),} + +\item{subscript, superscript}{character Text for a subscript and superscript +to \emph{P} symbol.} + +\item{df, df1, df2}{numeric The degrees of freedom of the estimate.} + +\item{method}{character The method used to estimate correlation, which +selects the symbol used for the value.} + +\item{conf.level}{numeric critical \emph{P}-value expressed as fraction in +[0..1].} + +\item{range.brackets, range.sep}{character Strings used to format a range.} +} +\value{ +A character string with formatting, encoded to be parsed as an R + plotmath expression, as plain text, as markdown or to be used with + \eqn{LaTeX} within \strong{math mode}. +} +\description{ +These functions format numeric values as character labels including the +symbol for statistical parameter estimates suitable for adding to plots. The +labels can be formatted as strings to be parsed as plotmath expressions, +or encoded using LaTeX or Markdown. +} +\examples{ +plain_label(value = 123, value.name = "n", output.type = "expression") +plain_label(value = 123, value.name = "n", output.type = "markdown") +plain_label(value = 123, value.name = "n", output.type = "latex") +italic_label(value = 123, value.name = "n", output.type = "expression") +italic_label(value = 123, value.name = "n", output.type = "markdown") +italic_label(value = 123, value.name = "n", output.type = "latex") +bold_label(value = 123, value.name = "n", output.type = "expression") +bold_label(value = 123, value.name = "n", output.type = "markdown") +bold_label(value = 123, value.name = "n", output.type = "latex") + +p_value_label(value = 0.345, digits = 2, output.type = "expression") +p_value_label(value = 0.345, digits = Inf, output.type = "expression") +p_value_label(value = 0.345, digits = 6, output.type = "expression") +p_value_label(value = 0.345, output.type = "markdown") +p_value_label(value = 0.345, output.type = "latex") +p_value_label(value = 0.345, subscript = "Holm") +p_value_label(value = 1e-25, digits = Inf, output.type = "expression") + +f_value_label(value = 123.4567, digits = 2, output.type = "expression") +f_value_label(value = 123.4567, digits = Inf, output.type = "expression") +f_value_label(value = 123.4567, digits = 6, output.type = "expression") +f_value_label(value = 123.4567, output.type = "markdown") +f_value_label(value = 123.4567, output.type = "latex") +f_value_label(value = 123.4567, df1 = 3, df2 = 123, + digits = 2, output.type = "expression") +f_value_label(value = 123.4567, df1 = 3, df2 = 123, + digits = 2, output.type = "latex") + +t_value_label(value = 123.4567, digits = 2, output.type = "expression") +t_value_label(value = 123.4567, digits = Inf, output.type = "expression") +t_value_label(value = 123.4567, digits = 6, output.type = "expression") +t_value_label(value = 123.4567, output.type = "markdown") +t_value_label(value = 123.4567, output.type = "latex") +t_value_label(value = 123.4567, df = 12, + digits = 2, output.type = "expression") +t_value_label(value = 123.4567, df = 123, + digits = 2, output.type = "latex") + +r_label(value = 0.95, digits = 2, output.type = "expression") +r_label(value = -0.95, digits = 2, output.type = "expression") +r_label(value = 0.0001, digits = 2, output.type = "expression") +r_label(value = -0.0001, digits = 2, output.type = "expression") +r_label(value = 0.1234567890, digits = Inf, output.type = "expression") +r_label(value = 0.95, digits = 2, method = "pearson") +r_label(value = 0.95, digits = 2, method = "kendall") +r_label(value = 0.95, digits = 2, method = "spearman") + +rr_label(value = 0.95, digits = 2, output.type = "expression") +rr_label(value = 0.0001, digits = 2, output.type = "expression") + +adj_rr_label(value = 0.95, digits = 2, output.type = "expression") +adj_rr_label(value = 0.0001, digits = 2, output.type = "expression") + +rr_ci_label(value = c(0.3, 0.4), conf.level = 0.95) +rr_ci_label(value = c(0.3, 0.4), conf.level = 0.95, output.type = "text") +rr_ci_label(value = c(0.3, 0.4), conf.level = 0.95, range.sep = ",") + +r_ci_label(value = c(-0.3, 0.4), conf.level = 0.95) +r_ci_label(value = c(-0.3, 0.4), conf.level = 0.95, output.type = "text") +r_ci_label(value = c(-0.3, 0.4), conf.level = 0.95, range.sep = ",") + +} +\seealso{ +\code{\link{sprintf_dm}} +} diff --git a/man/poly2character.Rd b/man/poly2character.Rd new file mode 100644 index 0000000..0b3e071 --- /dev/null +++ b/man/poly2character.Rd @@ -0,0 +1,37 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utilities-eq-label.R +\name{poly2character} +\alias{poly2character} +\title{Convert a polynomial into character string} +\usage{ +poly2character(x, decreasing = FALSE, digits = 3, keep.zeros = TRUE) +} +\arguments{ +\item{x}{a \code{polynomial} object.} + +\item{decreasing}{logical It specifies the order of the terms; in increasing +(default) or decreasing powers.} + +\item{digits}{integer Giving the number of significant digits to use for +printing.} + +\item{keep.zeros}{logical It indicates if zeros are to be retained in the +formatted coefficients.} +} +\value{ +A \code{character} string. +} +\description{ +Differs from \code{polynom::as.character.polynomial()} in that trailing zeros +are preserved. +} +\note{ +This is an edit of the code in package 'polynom' so that trailing zeros are + retained during the conversion. It is not defined using a different name + so as not to interfere with the original. +} +\examples{ +poly2character(1:3) +poly2character(1:3, decreasing = TRUE) + +} diff --git a/man/sprintf_dm.Rd b/man/sprintf_dm.Rd new file mode 100644 index 0000000..50cb73f --- /dev/null +++ b/man/sprintf_dm.Rd @@ -0,0 +1,61 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utilities-labels.R +\name{sprintf_dm} +\alias{sprintf_dm} +\alias{value2char} +\title{Format numeric values as strings} +\usage{ +sprintf_dm(fmt, ..., decimal.mark = getOption("OutDec", default = ".")) + +value2char( + value, + digits = Inf, + fixed = FALSE, + output.type = "expression", + decimal.mark = getOption("OutDec", default = ".") +) +} +\arguments{ +\item{fmt}{character as in \code{sprintf()}.} + +\item{...}{as in \code{sprintf()}.} + +\item{decimal.mark}{character If \code{NULL} or \code{NA} no substitution is +attempted and the value returned by \code{sprintf()} is returned as is.} + +\item{value}{numeric The value of the estimate.} + +\item{digits}{integer Number of digits to which numeric values are formatetd.} + +\item{fixed}{logical Interpret \code{digits} as indicating a number of +digits after the decimal mark or as the number of significant digits.} + +\item{output.type}{character One of "expression", "latex", "tex", "text", +"tikz", "markdown".} +} +\description{ +Using \code{\link{sprintf}} flexibly format numbers as character strings +encoded for parsing into R expressions or using \eqn{\LaTeX} or markdown +notation. +} +\details{ +These functions are used to format the character strings returned, + which can be used as labels in plots. Encoding used for the formatting is + selected by the argument passed to \code{output.type}, thus, supporting + different R graphic devices. +} +\examples{ + +sprintf_dm("\%2.3f", 2.34) +sprintf_dm("\%2.3f", 2.34, decimal.mark = ",") + + +value2char(2.34) +value2char(2.34, digits = 3, fixed = FALSE) +value2char(2.34, digits = 3, fixed = TRUE) +value2char(2.34, output.type = "text") + +} +\seealso{ +\code{\link[base]{sprintf}} +} diff --git a/man/stat_ma_eq.Rd b/man/stat_ma_eq.Rd index 8e029c8..93a9421 100644 --- a/man/stat_ma_eq.Rd +++ b/man/stat_ma_eq.Rd @@ -23,6 +23,7 @@ stat_ma_eq( small.p = FALSE, coef.digits = 3, coef.keep.zeros = TRUE, + decreasing = FALSE, rr.digits = 2, theta.digits = 2, p.digits = max(1, ceiling(log10(nperm))), @@ -92,6 +93,9 @@ the fitted coefficients.} \item{coef.keep.zeros}{logical Keep or drop trailing zeros when formatting the fitted coefficients and F-value.} +\item{decreasing}{logical It specifies the order of the terms in the +returned character string; in increasing (default) or decreasing powers.} + \item{rr.digits, theta.digits, p.digits}{integer Number of digits after the decimal point to use for R^2, theta and P-value in labels. If \code{Inf}, use exponential notation with three decimal places.} @@ -187,6 +191,17 @@ For backward compatibility a logical is accepted as argument for is rendered, i.e., displayed or printed. Set \code{options(OutDec = ",")} for languages like Spanish or French. } +\section{Warning!}{ + For the formatted equation to be valid, the fitted model + must be a polynomial, with or without intercept. If defined using + \code{poly()} the argument \code{raw = TRUE} must be passed. If defined + manually as powers of \code{x}, \strong{the terms must be in order of + increasing powers, with no missing intermediate power term.} Please, see + examples below. Currently, no check on the model is used to validate that + it is a polynomial, so failing to comply with this requirement results in + the silent output of an erroneous formatted equation. +} + \section{Aesthetics}{ \code{stat_ma_eq} understands \code{x} and \code{y}, to be referenced in the \code{formula} while the \code{weight} aesthetic is @@ -246,16 +261,26 @@ ggplot(my.data, aes(x, y)) + stat_ma_line() + stat_ma_eq() +ggplot(my.data, aes(x, y)) + + geom_point() + + stat_ma_line() + + stat_ma_eq(mapping = use_label("eq")) + +ggplot(my.data, aes(x, y)) + + geom_point() + + stat_ma_line() + + stat_ma_eq(mapping = use_label("eq"), decreasing = TRUE) + # use_label() can assemble and map a combined label ggplot(my.data, aes(x, y)) + geom_point() + stat_ma_line(method = "MA") + - stat_ma_eq(use_label(c("eq", "R2", "P"))) + stat_ma_eq(mapping = use_label(c("eq", "R2", "P"))) ggplot(my.data, aes(x, y)) + geom_point() + stat_ma_line(method = "MA") + - stat_ma_eq(use_label(c("R2", "P", "theta", "method"))) + stat_ma_eq(mapping = use_label(c("R2", "P", "theta", "method"))) # using ranged major axis regression ggplot(my.data, aes(x, y)) + @@ -263,7 +288,7 @@ ggplot(my.data, aes(x, y)) + stat_ma_line(method = "RMA", range.y = "interval", range.x = "interval") + - stat_ma_eq(use_label(c("eq", "R2", "P")), + stat_ma_eq(mapping = use_label(c("eq", "R2", "P")), method = "RMA", range.y = "interval", range.x = "interval") @@ -272,7 +297,7 @@ ggplot(my.data, aes(x, y)) + ggplot(my.data, aes(x, y)) + geom_point() + stat_ma_line(method = "MA") + - stat_ma_eq(use_label(c("eq", "R2")), + stat_ma_eq(mapping = use_label(c("eq", "R2")), method = "MA", nperm = 0) @@ -281,13 +306,13 @@ ggplot(my.data, aes(x, y)) + geom_point() + stat_ma_line(formula = x ~ y) + stat_ma_eq(formula = x ~ y, - use_label(c("eq", "R2", "P"))) + mapping = use_label(c("eq", "R2", "P"))) # modifying both variables within aes() ggplot(my.data, aes(log(x + 10), log(y + 10))) + geom_point() + stat_poly_line() + - stat_poly_eq(use_label("eq"), + stat_poly_eq(mapping = use_label("eq"), eq.x.rhs = "~~log(x+10)", eq.with.lhs = "log(y+10)~~`=`~~") @@ -302,7 +327,7 @@ ggplot(my.data, aes(x, y, shape = group, linetype = group, grp.label = group)) + geom_point() + stat_ma_line(color = "black") + - stat_ma_eq(use_label(c("grp", "eq", "R2"))) + + stat_ma_eq(mapping = use_label(c("grp", "eq", "R2"))) + theme_classic() # Inspecting the returned data using geom_debug() @@ -324,7 +349,7 @@ if (gginnards.installed) if (gginnards.installed) ggplot(my.data, aes(x, y)) + geom_point() + - stat_ma_eq(aes(label = after_stat(eq.label)), + stat_ma_eq(mapping = aes(label = after_stat(eq.label)), geom = "debug", output.type = "markdown") diff --git a/man/stat_poly_eq.Rd b/man/stat_poly_eq.Rd index 7ca5ca1..e3297eb 100644 --- a/man/stat_poly_eq.Rd +++ b/man/stat_poly_eq.Rd @@ -22,6 +22,7 @@ stat_poly_eq( rsquared.conf.level = 0.95, coef.digits = 3, coef.keep.zeros = TRUE, + decreasing = FALSE, rr.digits = 2, f.digits = 3, p.digits = 3, @@ -94,6 +95,9 @@ the fitted coefficients and F-value.} \item{coef.keep.zeros}{logical Keep or drop trailing zeros when formatting the fitted coefficients and F-value.} +\item{decreasing}{logical It specifies the order of the terms in the +returned character string; in increasing (default) or decreasing powers.} + \item{rr.digits, p.digits}{integer Number of digits after the decimal point to use for \eqn{R^2} and P-value in labels. If \code{Inf}, use exponential notation with three decimal places.} @@ -213,6 +217,17 @@ For backward compatibility a logical is accepted as argument for is rendered, i.e., displayed or printed. Set \code{options(OutDec = ",")} for languages like Spanish or French. } +\section{Warning!}{ + For the formatted equation to be valid, the fitted model + must be a polynomial, with or without intercept. If defined using + \code{poly()} the argument \code{raw = TRUE} must be passed. If defined + manually as powers of \code{x}, \strong{the terms must be in order of + increasing powers, with no missing intermediate power term.} Please, see + examples below. Currently, no check on the model is used to validate that + it is a polynomial, so failing to comply with this requirement results in + the silent output of an erroneous formatted equation. +} + \section{Aesthetics}{ \code{stat_poly_eq()} understands \code{x} and \code{y}, to be referenced in the \code{formula} and \code{weight} passed as argument @@ -307,6 +322,12 @@ ggplot(my.data, aes(x, y)) + stat_poly_line(formula = formula) + stat_poly_eq(use_label("eq"), formula = formula) +# other labels +ggplot(my.data, aes(x, y)) + + geom_point() + + stat_poly_line(formula = formula) + + stat_poly_eq(use_label("eq"), formula = formula, decreasing = TRUE) + ggplot(my.data, aes(x, y)) + geom_point() + stat_poly_line(formula = formula) + diff --git a/man/stat_quant_eq.Rd b/man/stat_quant_eq.Rd index 0ebcb16..a6db619 100644 --- a/man/stat_quant_eq.Rd +++ b/man/stat_quant_eq.Rd @@ -19,7 +19,8 @@ stat_quant_eq( eq.x.rhs = NULL, coef.digits = 3, coef.keep.zeros = TRUE, - rho.digits = 2, + decreasing = FALSE, + rho.digits = 4, label.x = "left", label.y = "top", label.x.npc = NULL, @@ -82,6 +83,9 @@ the fitted coefficients and rho in labels.} \item{coef.keep.zeros}{logical Keep or drop trailing zeros when formatting the fitted coefficients and F-value.} +\item{decreasing}{logical It specifies the order of the terms in the +returned character string; in increasing (default) or decreasing powers.} + \item{label.x, label.y}{\code{numeric} with range 0..1 "normalized parent coordinates" (npc units) or character if using \code{geom_text_npc()} or \code{geom_label_npc()}. If using \code{geom_text()} or \code{geom_label()} @@ -200,6 +204,17 @@ Support for the \code{angle} aesthetic is not automatic and requires that the user passes as argument suitable numeric values to override the defaults for label positions. } +\section{Warning!}{ + For the formatted equations to be valid, the fitted model + must be a polynomial, with or without intercept. If defined using + \code{poly()} the argument \code{raw = TRUE} must be passed. If defined + manually as powers of \code{x}, \strong{the terms must be in order of + increasing powers, with no missing intermediate power term.} Please, see + examples below. Currently, no check on the model is used to validate that + it is a polynomial, so failing to comply with this requirement results in + the silent output of an erroneous formatted equation. +} + \section{Aesthetics}{ \code{stat_quant_eq()} understands \code{x} and \code{y}, to be referenced in the \code{formula} and \code{weight} passed as argument @@ -274,7 +289,17 @@ ggplot(my.data, aes(x, y)) + ggplot(my.data, aes(x, y)) + geom_point() + stat_quant_line() + - stat_quant_eq(use_label(c("eq", "method"))) + stat_quant_eq(mapping = use_label("eq")) + +ggplot(my.data, aes(x, y)) + + geom_point() + + stat_quant_line() + + stat_quant_eq(mapping = use_label("eq"), decreasing = TRUE) + +ggplot(my.data, aes(x, y)) + + geom_point() + + stat_quant_line() + + stat_quant_eq(mapping = use_label(c("eq", "method"))) # same formula as default ggplot(my.data, aes(x, y)) + @@ -291,15 +316,15 @@ ggplot(my.data, aes(x, y)) + # using color ggplot(my.data, aes(x, y)) + geom_point() + - stat_quant_line(aes(color = after_stat(quantile.f))) + - stat_quant_eq(aes(color = after_stat(quantile.f))) + + stat_quant_line(mapping = aes(color = after_stat(quantile.f))) + + stat_quant_eq(mapping = aes(color = after_stat(quantile.f))) + labs(color = "Quantiles") # location and colour ggplot(my.data, aes(x, y)) + geom_point() + - stat_quant_line(aes(color = after_stat(quantile.f))) + - stat_quant_eq(aes(color = after_stat(quantile.f)), + stat_quant_line(mapping = aes(color = after_stat(quantile.f))) + + stat_quant_eq(mapping = aes(color = after_stat(quantile.f)), label.y = "bottom", label.x = "right") + labs(color = "Quantiles") @@ -349,7 +374,7 @@ ggplot(my.data, aes(x, y2, shape = group, linetype = group, grp.label = group)) + geom_point() + stat_quant_band(formula = formula, color = "black", linewidth = 0.75) + - stat_quant_eq(use_label(c("grp", "eq"), sep = "*\": \"*"), + stat_quant_eq(mapping = use_label(c("grp", "eq"), sep = "*\": \"*"), formula = formula) + expand_limits(y = 3) + theme_classic() @@ -360,7 +385,7 @@ formula.trans <- y ~ I(x^2) ggplot(my.data, aes(x, y + 1)) + geom_point() + stat_quant_line(formula = formula.trans) + - stat_quant_eq(use_label("eq"), + stat_quant_eq(mapping = use_label("eq"), formula = formula.trans, eq.x.rhs = "~x^2", eq.with.lhs = "y + 1~~`=`~~") @@ -381,10 +406,10 @@ ggplot(my.data, aes(x, y)) + ggplot(my.data, aes(x, y2, color = group, grp.label = group)) + geom_point() + stat_quant_line(method = "rq", formula = formula, - quantiles = c(0.05, 0.5, 0.95), - linewidth = 0.5) + - stat_quant_eq(aes(label = paste(after_stat(grp.label), "*\": \"*", - after_stat(eq.label), sep = "")), + quantiles = c(0.05, 0.5, 0.95), + linewidth = 0.5) + + stat_quant_eq(mapping = aes(label = paste(after_stat(grp.label), "*\": \"*", + after_stat(eq.label), sep = "")), quantiles = c(0.05, 0.5, 0.95), formula = formula, size = 3) @@ -393,9 +418,9 @@ ggplot(my.data, aes(x, y2, color = group, grp.label = group)) + geom_point() + stat_quant_band(method = "rq", formula = formula, quantiles = c(0.05, 0.5, 0.95)) + - stat_quant_eq(aes(label = sprintf("\%s*\": \"*\%s", - after_stat(grp.label), - after_stat(eq.label))), + stat_quant_eq(mapping = aes(label = sprintf("\%s*\": \"*\%s", + after_stat(grp.label), + after_stat(eq.label))), quantiles = c(0.05, 0.5, 0.95), formula = formula, size = 3) @@ -425,7 +450,7 @@ if (gginnards.installed) if (gginnards.installed) ggplot(my.data, aes(x, y)) + geom_point() + - stat_quant_eq(aes(label = after_stat(eq.label)), + stat_quant_eq(mapping = aes(label = after_stat(eq.label)), formula = formula, geom = "debug", output.type = "markdown") diff --git a/man/typeset_numbers.Rd b/man/typeset_numbers.Rd new file mode 100644 index 0000000..d2bb029 --- /dev/null +++ b/man/typeset_numbers.Rd @@ -0,0 +1,27 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utilities-eq-label.R +\name{typeset_numbers} +\alias{typeset_numbers} +\title{Typeset/format numbers preserving trailing zeros} +\usage{ +typeset_numbers(eq.char, output.type) +} +\arguments{ +\item{eq.char}{character A polynomial model equation as a character string.} + +\item{output.type}{character One of "expression", "latex", "tex", "text", +"tikz", "markdown".} +} +\value{ +A \code{character} string. +} +\description{ +Typeset/format numbers preserving trailing zeros +} +\note{ +exponential number notation to typeset equivalent: Protecting trailing + zeros in negative numbers is more involved than I would like. Not only we + need to enclose numbers in quotations marks but we also need to replace + dashes with the minus character. I am not sure we can do the replacement + portably, but that recent R supports UTF gives some hope. +} diff --git a/test/mising-equation/ggpmisc_stat_poly_eq_df.rds b/test/mising-equation/ggpmisc_stat_poly_eq_df.rds new file mode 100644 index 0000000..30af332 Binary files /dev/null and b/test/mising-equation/ggpmisc_stat_poly_eq_df.rds differ diff --git a/test/mising-equation/missing-equation-issue60.R b/test/mising-equation/missing-equation-issue60.R new file mode 100644 index 0000000..b11b668 --- /dev/null +++ b/test/mising-equation/missing-equation-issue60.R @@ -0,0 +1,15 @@ +library(tidyverse) +library(ggpmisc) + +test_df <- readRDS("test/mising-equation/ggpmisc_stat_poly_eq_df.rds") + +test_df %>% + subset(grp == "E") %>% + ggplot(aes(x = ref1, y = ref2, colour = grp)) + + geom_point() + + geom_smooth(method="lm" , color="black", fill='grey', se=TRUE, alpha = 0.5, linewidth =0.5) + + stat_poly_eq(use_label("eq"), label.x.npc = 0.055, label.y.npc = 0.88, color = "black", + coef.keep.zeros = FALSE) + + geom_abline(intercept = 0, slope = 1, linetype = "dashed", color = "blue", alpha =0.5) + + theme_bw() + + facet_wrap(~grp) diff --git a/tests/testthat/_snaps/stat-corr/stat-coor-kendall-roundinf.svg b/tests/testthat/_snaps/stat-corr/stat-coor-kendall-roundinf.svg index 62e4934..3b8c25e 100644 --- a/tests/testthat/_snaps/stat-corr/stat-coor-kendall-roundinf.svg +++ b/tests/testthat/_snaps/stat-corr/stat-coor-kendall-roundinf.svg @@ -151,15 +151,14 @@ 5.22 × 10 - -32 - - -n - -= - -100 +−32 + + +n + += + +100 diff --git a/tests/testthat/_snaps/stat-corr/stat-coor-pearson-round-inf.svg b/tests/testthat/_snaps/stat-corr/stat-coor-pearson-round-inf.svg index 1b0dc8c..288d4e3 100644 --- a/tests/testthat/_snaps/stat-corr/stat-coor-pearson-round-inf.svg +++ b/tests/testthat/_snaps/stat-corr/stat-coor-pearson-round-inf.svg @@ -152,15 +152,14 @@ 7.21 × 10 - -50 - - -n - -= - -100 +−50 + + +n + += + +100 diff --git a/tests/testthat/_snaps/stat-corr/stat-coor-spearman-round-inf.svg b/tests/testthat/_snaps/stat-corr/stat-coor-spearman-round-inf.svg index df7edc1..c691c65 100644 --- a/tests/testthat/_snaps/stat-corr/stat-coor-spearman-round-inf.svg +++ b/tests/testthat/_snaps/stat-corr/stat-coor-spearman-round-inf.svg @@ -141,29 +141,27 @@ = -8.84 -× -10 -+ -3 - - -P - -= - -0 -× -10 -+ -0 - - -n - -= - -100 +8.8 +× +10 ++03 + + +P + += + +0.00 +× +10 ++00 + + +n + += + +100 diff --git a/tests/testthat/_snaps/stat-corr/stat-coor-spearman-round2.svg b/tests/testthat/_snaps/stat-corr/stat-coor-spearman-round2.svg index 0b5883e..6e48023 100644 --- a/tests/testthat/_snaps/stat-corr/stat-coor-spearman-round2.svg +++ b/tests/testthat/_snaps/stat-corr/stat-coor-spearman-round2.svg @@ -141,25 +141,24 @@ = -8.84 -× -10 -+ -3 - - -P - -< - -0.01 - - -n - -= - -100 +8.8 +× +10 ++03 + + +P + +< + +0.01 + + +n + += + +100 diff --git a/tests/testthat/_snaps/stat-corr/stat-correlation-kendall-exact.svg b/tests/testthat/_snaps/stat-corr/stat-correlation-kendall-exact.svg index d77300b..86b88ca 100644 --- a/tests/testthat/_snaps/stat-corr/stat-correlation-kendall-exact.svg +++ b/tests/testthat/_snaps/stat-corr/stat-correlation-kendall-exact.svg @@ -141,25 +141,24 @@ = -4.452 -× -10 -+ -3 - - -P - -< - -0.001 - - -n - -= - -100 +4.45 +× +10 ++03 + + +P + +< + +0.001 + + +n + += + +100 diff --git a/tests/testthat/_snaps/stat-corr/stat-correlation-spearman-cont.svg b/tests/testthat/_snaps/stat-corr/stat-correlation-spearman-cont.svg index 7ad76a8..b16fef3 100644 --- a/tests/testthat/_snaps/stat-corr/stat-correlation-spearman-cont.svg +++ b/tests/testthat/_snaps/stat-corr/stat-correlation-spearman-cont.svg @@ -141,25 +141,24 @@ = -8.844 -× -10 -+ -3 - - -P - -< - -0.001 - - -n - -= - -100 +8.84 +× +10 ++03 + + +P + +< + +0.001 + + +n + += + +100 diff --git a/tests/testthat/_snaps/stat-corr/stat-correlation-spearman-exact.svg b/tests/testthat/_snaps/stat-corr/stat-correlation-spearman-exact.svg index 44c825e..63cad40 100644 --- a/tests/testthat/_snaps/stat-corr/stat-correlation-spearman-exact.svg +++ b/tests/testthat/_snaps/stat-corr/stat-correlation-spearman-exact.svg @@ -141,25 +141,24 @@ = -8.844 -× -10 -+ -3 - - -P - -< - -0.001 - - -n - -= - -100 +8.84 +× +10 ++03 + + +P + +< + +0.001 + + +n + += + +100 diff --git a/tests/testthat/_snaps/stat-corr/stat-correlation-spearman-load.svg b/tests/testthat/_snaps/stat-corr/stat-correlation-spearman-load.svg index 5b70ad1..f3994ff 100644 --- a/tests/testthat/_snaps/stat-corr/stat-correlation-spearman-load.svg +++ b/tests/testthat/_snaps/stat-corr/stat-correlation-spearman-load.svg @@ -141,25 +141,24 @@ = -8.844 -× -10 -+ -3 - - -P - -< - -0.001 - - -n - -= - -100 +8.84 +× +10 ++03 + + +P + +< + +0.001 + + +n + += + +100 diff --git a/tests/testthat/_snaps/stat-corr/stat-correlation-spearman-noload-use-label-lc.svg b/tests/testthat/_snaps/stat-corr/stat-correlation-spearman-noload-use-label-lc.svg index b44ee66..467584b 100644 --- a/tests/testthat/_snaps/stat-corr/stat-correlation-spearman-noload-use-label-lc.svg +++ b/tests/testthat/_snaps/stat-corr/stat-correlation-spearman-noload-use-label-lc.svg @@ -141,25 +141,24 @@ = -8.844 -× -10 -+ -3 - - -P - -< - -0.001 - - -n - -= - -100 +8.84 +× +10 ++03 + + +P + +< + +0.001 + + +n + += + +100 diff --git a/tests/testthat/_snaps/stat-corr/stat-correlation-spearman-noload-use-label.svg b/tests/testthat/_snaps/stat-corr/stat-correlation-spearman-noload-use-label.svg index 96afa81..5b32bac 100644 --- a/tests/testthat/_snaps/stat-corr/stat-correlation-spearman-noload-use-label.svg +++ b/tests/testthat/_snaps/stat-corr/stat-correlation-spearman-noload-use-label.svg @@ -141,25 +141,24 @@ = -8.844 -× -10 -+ -3 - - -P - -< - -0.001 - - -n - -= - -100 +8.84 +× +10 ++03 + + +P + +< + +0.001 + + +n + += + +100 diff --git a/tests/testthat/_snaps/stat-corr/stat-correlation-spearman-noload.svg b/tests/testthat/_snaps/stat-corr/stat-correlation-spearman-noload.svg index d5732b4..6346702 100644 --- a/tests/testthat/_snaps/stat-corr/stat-correlation-spearman-noload.svg +++ b/tests/testthat/_snaps/stat-corr/stat-correlation-spearman-noload.svg @@ -141,25 +141,24 @@ = -8.844 -× -10 -+ -3 - - -P - -< - -0.001 - - -n - -= - -100 +8.84 +× +10 ++03 + + +P + +< + +0.001 + + +n + += + +100 diff --git a/tests/testthat/_snaps/stat-ma-eq/stat-ma-eq-formula-x-round-inf.svg b/tests/testthat/_snaps/stat-ma-eq/stat-ma-eq-formula-x-round-inf.svg index 20aed40..8afd96a 100644 --- a/tests/testthat/_snaps/stat-ma-eq/stat-ma-eq-formula-x-round-inf.svg +++ b/tests/testthat/_snaps/stat-ma-eq/stat-ma-eq-formula-x-round-inf.svg @@ -155,18 +155,17 @@ = -1 -× -10 - -2 - - -n - -= - -100 +1.00 +× +10 +−02 + + +n + += + +100 diff --git a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-bars-dunnet-many-levels.svg b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-bars-dunnet-many-levels.svg index ce94270..6395af3 100644 --- a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-bars-dunnet-many-levels.svg +++ b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-bars-dunnet-many-levels.svg @@ -70,7 +70,10 @@ P -Dnnt +D +n +n +t = @@ -78,7 +81,10 @@ P -Dnnt +D +n +n +t = @@ -86,7 +92,10 @@ P -Dnnt +D +n +n +t < @@ -94,7 +103,10 @@ P -Dnnt +D +n +n +t < @@ -102,7 +114,10 @@ P -Dnnt +D +n +n +t = @@ -110,7 +125,10 @@ P -Dnnt +D +n +n +t = @@ -118,7 +136,10 @@ P -Dnnt +D +n +n +t < @@ -126,7 +147,10 @@ P -Dnnt +D +n +n +t < @@ -134,7 +158,10 @@ P -Dnnt +D +n +n +t < diff --git a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-bars-dunnet.svg b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-bars-dunnet.svg index b788097..19d220b 100644 --- a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-bars-dunnet.svg +++ b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-bars-dunnet.svg @@ -50,7 +50,10 @@ P -Dnnt +D +n +n +t = @@ -58,7 +61,10 @@ P -Dnnt +D +n +n +t < @@ -66,7 +72,10 @@ P -Dnnt +D +n +n +t < @@ -74,7 +83,10 @@ P -Dnnt +D +n +n +t < diff --git a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-bars-tukey.svg b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-bars-tukey.svg index ac99d36..26daa6c 100644 --- a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-bars-tukey.svg +++ b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-bars-tukey.svg @@ -50,7 +50,9 @@ P -HSD +H +S +D = @@ -58,7 +60,9 @@ P -HSD +H +S +D < @@ -66,7 +70,9 @@ P -HSD +H +S +D < @@ -74,7 +80,9 @@ P -HSD +H +S +D < @@ -82,7 +90,9 @@ P -HSD +H +S +D = @@ -90,7 +100,9 @@ P -HSD +H +S +D < @@ -98,7 +110,9 @@ P -HSD +H +S +D < @@ -106,7 +120,9 @@ P -HSD +H +S +D = @@ -114,7 +130,9 @@ P -HSD +H +S +D < @@ -122,7 +140,9 @@ P -HSD +H +S +D = diff --git a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-bars-tukey2.svg b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-bars-tukey2.svg index 07e3d99..4f79aea 100644 --- a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-bars-tukey2.svg +++ b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-bars-tukey2.svg @@ -51,14 +51,18 @@ - -P -HSD -crit - -= - -0.05 +P +H +S +D +c +r +i +t + += + +0.050 c c d diff --git a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-bonferroni-dunnet.svg b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-bonferroni-dunnet.svg index 566500f..2cf1e29 100644 --- a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-bonferroni-dunnet.svg +++ b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-bonferroni-dunnet.svg @@ -50,7 +50,10 @@ P -bnfr +b +n +f +r = @@ -58,7 +61,10 @@ P -bnfr +b +n +f +r < @@ -66,7 +72,10 @@ P -bnfr +b +n +f +r < @@ -74,7 +83,10 @@ P -bnfr +b +n +f +r < diff --git a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-bonferroni-tukey.svg b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-bonferroni-tukey.svg index eb40fd0..4ff993c 100644 --- a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-bonferroni-tukey.svg +++ b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-bonferroni-tukey.svg @@ -50,7 +50,10 @@ P -bnfr +b +n +f +r = @@ -58,7 +61,10 @@ P -bnfr +b +n +f +r < @@ -66,7 +72,10 @@ P -bnfr +b +n +f +r < @@ -74,7 +83,10 @@ P -bnfr +b +n +f +r < @@ -82,7 +94,10 @@ P -bnfr +b +n +f +r = @@ -90,7 +105,10 @@ P -bnfr +b +n +f +r < @@ -98,7 +116,10 @@ P -bnfr +b +n +f +r < @@ -106,7 +127,10 @@ P -bnfr +b +n +f +r = @@ -114,7 +138,10 @@ P -bnfr +b +n +f +r < @@ -122,7 +149,10 @@ P -bnfr +b +n +f +r = diff --git a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-letters-label-tukey.svg b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-letters-label-tukey.svg index 0a4df2f..1c29db3 100644 --- a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-letters-label-tukey.svg +++ b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-letters-label-tukey.svg @@ -47,15 +47,19 @@ - - -P -HSD -crit - -= - -0.05 + +P +H +S +D +c +r +i +t + += + +0.050 c diff --git a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-letters-tukey-mixed.svg b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-letters-tukey-mixed.svg index b904218..1a941e8 100644 --- a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-letters-tukey-mixed.svg +++ b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-letters-tukey-mixed.svg @@ -47,14 +47,18 @@ - -P -HSD -crit - -= - -0.05 +P +H +S +D +c +r +i +t + += + +0.050 a c d diff --git a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-letters-tukey-rev.svg b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-letters-tukey-rev.svg index b17dad4..978ef81 100644 --- a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-letters-tukey-rev.svg +++ b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-letters-tukey-rev.svg @@ -47,14 +47,18 @@ - -P -HSD -crit - -= - -0.05 +P +H +S +D +c +r +i +t + += + +0.050 c c d diff --git a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-letters-tukey.svg b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-letters-tukey.svg index 60dd0c7..98b5b99 100644 --- a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-letters-tukey.svg +++ b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-letters-tukey.svg @@ -47,14 +47,18 @@ - -P -HSD -crit - -= - -0.05 +P +H +S +D +c +r +i +t + += + +0.050 c c d diff --git a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-lm-char.svg b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-lm-char.svg index 42b8999..1a795a5 100644 --- a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-lm-char.svg +++ b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-lm-char.svg @@ -50,7 +50,9 @@ P -HSD +H +S +D = @@ -58,7 +60,9 @@ P -HSD +H +S +D < @@ -66,7 +70,9 @@ P -HSD +H +S +D < @@ -74,7 +80,9 @@ P -HSD +H +S +D < @@ -82,7 +90,9 @@ P -HSD +H +S +D = @@ -90,7 +100,9 @@ P -HSD +H +S +D < @@ -98,7 +110,9 @@ P -HSD +H +S +D < @@ -106,7 +120,9 @@ P -HSD +H +S +D = @@ -114,7 +130,9 @@ P -HSD +H +S +D < @@ -122,7 +140,9 @@ P -HSD +H +S +D = diff --git a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-lm-char2.svg b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-lm-char2.svg index 9046436..be6652a 100644 --- a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-lm-char2.svg +++ b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-lm-char2.svg @@ -50,7 +50,9 @@ P -HSD +H +S +D = @@ -58,7 +60,9 @@ P -HSD +H +S +D < @@ -66,7 +70,9 @@ P -HSD +H +S +D < @@ -74,7 +80,9 @@ P -HSD +H +S +D < @@ -82,7 +90,9 @@ P -HSD +H +S +D = @@ -90,7 +100,9 @@ P -HSD +H +S +D < @@ -98,7 +110,9 @@ P -HSD +H +S +D < @@ -106,7 +120,9 @@ P -HSD +H +S +D = @@ -114,7 +130,9 @@ P -HSD +H +S +D < @@ -122,7 +140,9 @@ P -HSD +H +S +D = diff --git a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-lm-fun.svg b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-lm-fun.svg index f285329..c54755f 100644 --- a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-lm-fun.svg +++ b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-lm-fun.svg @@ -50,7 +50,9 @@ P -HSD +H +S +D = @@ -58,7 +60,9 @@ P -HSD +H +S +D < @@ -66,7 +70,9 @@ P -HSD +H +S +D < @@ -74,7 +80,9 @@ P -HSD +H +S +D < @@ -82,7 +90,9 @@ P -HSD +H +S +D = @@ -90,7 +100,9 @@ P -HSD +H +S +D < @@ -98,7 +110,9 @@ P -HSD +H +S +D < @@ -106,7 +120,9 @@ P -HSD +H +S +D = @@ -114,7 +130,9 @@ P -HSD +H +S +D < @@ -122,7 +140,9 @@ P -HSD +H +S +D = diff --git a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-lm-fun2.svg b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-lm-fun2.svg index c4898e4..64b7039 100644 --- a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-lm-fun2.svg +++ b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-lm-fun2.svg @@ -50,7 +50,9 @@ P -HSD +H +S +D = @@ -58,7 +60,9 @@ P -HSD +H +S +D < @@ -66,7 +70,9 @@ P -HSD +H +S +D < @@ -74,7 +80,9 @@ P -HSD +H +S +D < @@ -82,7 +90,9 @@ P -HSD +H +S +D = @@ -90,7 +100,9 @@ P -HSD +H +S +D < @@ -98,7 +110,9 @@ P -HSD +H +S +D < @@ -106,7 +120,9 @@ P -HSD +H +S +D = @@ -114,7 +130,9 @@ P -HSD +H +S +D < @@ -122,7 +140,9 @@ P -HSD +H +S +D = diff --git a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-noload-more.svg b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-noload-more.svg index 85c245b..652ea82 100644 --- a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-noload-more.svg +++ b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-noload-more.svg @@ -46,7 +46,9 @@ 20.2 , P -HSD +H +S +D = @@ -60,7 +62,9 @@ 42.2 , P -HSD +H +S +D < @@ -74,7 +78,9 @@ 66. , P -HSD +H +S +D < @@ -88,7 +94,9 @@ 82.9 , P -HSD +H +S +D < @@ -102,7 +110,9 @@ 22.0 , P -HSD +H +S +D = @@ -116,7 +126,9 @@ 45.8 , P -HSD +H +S +D < @@ -130,7 +142,9 @@ 62.7 , P -HSD +H +S +D < @@ -144,7 +158,9 @@ 23.8 , P -HSD +H +S +D = @@ -158,7 +174,9 @@ 40.7 , P -HSD +H +S +D < @@ -172,7 +190,9 @@ 16.9 , P -HSD +H +S +D = diff --git a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-noload.svg b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-noload.svg index e8e83f0..328bd0e 100644 --- a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-noload.svg +++ b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-noload.svg @@ -50,7 +50,9 @@ P -HSD +H +S +D = @@ -58,7 +60,9 @@ P -HSD +H +S +D < @@ -66,7 +70,9 @@ P -HSD +H +S +D < @@ -74,7 +80,9 @@ P -HSD +H +S +D < @@ -82,7 +90,9 @@ P -HSD +H +S +D = @@ -90,7 +100,9 @@ P -HSD +H +S +D < @@ -98,7 +110,9 @@ P -HSD +H +S +D < @@ -106,7 +120,9 @@ P -HSD +H +S +D = @@ -114,7 +130,9 @@ P -HSD +H +S +D < @@ -122,7 +140,9 @@ P -HSD +H +S +D = diff --git a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-p-digits-inf.svg b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-p-digits-inf.svg index 2f39ff3..50ff6cb 100644 --- a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-p-digits-inf.svg +++ b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-p-digits-inf.svg @@ -48,125 +48,135 @@ - -P -HSD - -= - -2.23 -× -10 - -1 + +P +H +S +D + += + +2.23 +× +10 +−01 - -P -HSD - -= - -2.47 -× -10 - -4 + +P +H +S +D + += + +2.47 +× +10 +−04 - -P -HSD - -= - -2.27 -× -10 - -9 + +P +H +S +D + += + +2.27 +× +10 +−09 - -P -HSD - -= - -2.96 -× -10 - -13 + +P +H +S +D + += + +2.96 +× +10 +−13 - -P -HSD - -= - -1.51 -× -10 - -1 + +P +H +S +D + += + +1.51 +× +10 +−01 - -P -HSD - -= - -5.38 -× -10 - -5 + +P +H +S +D + += + +5.38 +× +10 +−05 - -P -HSD - -= - -2.69 -× -10 - -8 + +P +H +S +D + += + +2.69 +× +10 +−08 - -P -HSD - -= - -1.02 -× -10 - -1 + +P +H +S +D + += + +1.02 +× +10 +−01 - -P -HSD - -= - -4.4 -× -10 - -4 + +P +H +S +D + += + +4.40 +× +10 +−04 - -P -HSD - -= - -3.95 -× -10 - -1 + +P +H +S +D + += + +3.95 +× +10 +−01 diff --git a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-p-digits2.svg b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-p-digits2.svg index 5a0fdb4..8bcf389 100644 --- a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-p-digits2.svg +++ b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-p-digits2.svg @@ -50,7 +50,9 @@ P -HSD +H +S +D = @@ -58,7 +60,9 @@ P -HSD +H +S +D < @@ -66,7 +70,9 @@ P -HSD +H +S +D < @@ -74,7 +80,9 @@ P -HSD +H +S +D < @@ -82,7 +90,9 @@ P -HSD +H +S +D = @@ -90,7 +100,9 @@ P -HSD +H +S +D < @@ -98,7 +110,9 @@ P -HSD +H +S +D < @@ -106,7 +120,9 @@ P -HSD +H +S +D = @@ -114,7 +130,9 @@ P -HSD +H +S +D < @@ -122,7 +140,9 @@ P -HSD +H +S +D = diff --git a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-p-digits6.svg b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-p-digits6.svg index bb67f5b..4830198 100644 --- a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-p-digits6.svg +++ b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-p-digits6.svg @@ -50,7 +50,9 @@ P -HSD +H +S +D = @@ -58,7 +60,9 @@ P -HSD +H +S +D = @@ -66,7 +70,9 @@ P -HSD +H +S +D < @@ -74,7 +80,9 @@ P -HSD +H +S +D < @@ -82,7 +90,9 @@ P -HSD +H +S +D = @@ -90,7 +100,9 @@ P -HSD +H +S +D = @@ -98,7 +110,9 @@ P -HSD +H +S +D < @@ -106,7 +120,9 @@ P -HSD +H +S +D = @@ -114,7 +130,9 @@ P -HSD +H +S +D = @@ -122,7 +140,9 @@ P -HSD +H +S +D = diff --git a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-rlm-char.svg b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-rlm-char.svg index 519f840..84599b4 100644 --- a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-rlm-char.svg +++ b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-rlm-char.svg @@ -50,7 +50,9 @@ P -HSD +H +S +D = @@ -58,7 +60,9 @@ P -HSD +H +S +D < @@ -66,7 +70,9 @@ P -HSD +H +S +D < @@ -74,7 +80,9 @@ P -HSD +H +S +D < @@ -82,7 +90,9 @@ P -HSD +H +S +D = @@ -90,7 +100,9 @@ P -HSD +H +S +D < @@ -98,7 +110,9 @@ P -HSD +H +S +D < @@ -106,7 +120,9 @@ P -HSD +H +S +D = @@ -114,7 +130,9 @@ P -HSD +H +S +D < @@ -122,7 +140,9 @@ P -HSD +H +S +D = diff --git a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-rlm-fun.svg b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-rlm-fun.svg index 4036f9c..f45a5d7 100644 --- a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-rlm-fun.svg +++ b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-rlm-fun.svg @@ -50,7 +50,9 @@ P -HSD +H +S +D = @@ -58,7 +60,9 @@ P -HSD +H +S +D < @@ -66,7 +70,9 @@ P -HSD +H +S +D < @@ -74,7 +80,9 @@ P -HSD +H +S +D < @@ -82,7 +90,9 @@ P -HSD +H +S +D = @@ -90,7 +100,9 @@ P -HSD +H +S +D < @@ -98,7 +110,9 @@ P -HSD +H +S +D < @@ -106,7 +120,9 @@ P -HSD +H +S +D = @@ -114,7 +130,9 @@ P -HSD +H +S +D < @@ -122,7 +140,9 @@ P -HSD +H +S +D = diff --git a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-text-pairwise-dunnet.svg b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-text-pairwise-dunnet.svg index 5777543..f8d169d 100644 --- a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-text-pairwise-dunnet.svg +++ b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-text-pairwise-dunnet.svg @@ -49,28 +49,40 @@ P -Dnnt +D +n +n +t = 0.118 P -Dnnt +D +n +n +t < 0.001 P -Dnnt +D +n +n +t < 0.001 P -Dnnt +D +n +n +t < diff --git a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-text-pairwise-tukey.svg b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-text-pairwise-tukey.svg index f779aac..ae15334 100644 --- a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-text-pairwise-tukey.svg +++ b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-text-pairwise-tukey.svg @@ -49,70 +49,90 @@ P -HSD +H +S +D = 0.22 P -HSD +H +S +D < 0.01 P -HSD +H +S +D < 0.01 P -HSD +H +S +D < 0.01 P -HSD +H +S +D = 0.15 P -HSD +H +S +D < 0.01 P -HSD +H +S +D < 0.01 P -HSD +H +S +D = 0.10 P -HSD +H +S +D < 0.01 P -HSD +H +S +D = diff --git a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-bottom-num-dunnet.svg b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-bottom-num-dunnet.svg index cb44378..29b01e8 100644 --- a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-bottom-num-dunnet.svg +++ b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-bottom-num-dunnet.svg @@ -50,7 +50,10 @@ P -Dnnt +D +n +n +t = @@ -58,7 +61,10 @@ P -Dnnt +D +n +n +t < @@ -66,7 +72,10 @@ P -Dnnt +D +n +n +t < @@ -74,7 +83,10 @@ P -Dnnt +D +n +n +t < diff --git a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-bottom-num-letters-tukey.svg b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-bottom-num-letters-tukey.svg index dd09d40..874d29b 100644 --- a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-bottom-num-letters-tukey.svg +++ b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-bottom-num-letters-tukey.svg @@ -47,14 +47,18 @@ - -P -HSD -crit - -= - -0.05 +P +H +S +D +c +r +i +t + += + +0.050 c c d diff --git a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-bottom-num-tukey.svg b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-bottom-num-tukey.svg index 2f31c1d..598f450 100644 --- a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-bottom-num-tukey.svg +++ b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-bottom-num-tukey.svg @@ -50,7 +50,9 @@ P -HSD +H +S +D = @@ -58,7 +60,9 @@ P -HSD +H +S +D < @@ -66,7 +70,9 @@ P -HSD +H +S +D < @@ -74,7 +80,9 @@ P -HSD +H +S +D < @@ -82,7 +90,9 @@ P -HSD +H +S +D = @@ -90,7 +100,9 @@ P -HSD +H +S +D < @@ -98,7 +110,9 @@ P -HSD +H +S +D < @@ -106,7 +120,9 @@ P -HSD +H +S +D = @@ -114,7 +130,9 @@ P -HSD +H +S +D < @@ -122,7 +140,9 @@ P -HSD +H +S +D = diff --git a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-bottom-tukey.svg b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-bottom-tukey.svg index bfaec0c..9f32b5b 100644 --- a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-bottom-tukey.svg +++ b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-bottom-tukey.svg @@ -47,14 +47,18 @@ - -P -HSD -crit - -= - -0.05 +P +H +S +D +c +r +i +t + += + +0.05 c c d diff --git a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-top-dunnet.svg b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-top-dunnet.svg index 94fff3d..86d94e5 100644 --- a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-top-dunnet.svg +++ b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-top-dunnet.svg @@ -50,7 +50,10 @@ P -Dnnt +D +n +n +t = @@ -58,7 +61,10 @@ P -Dnnt +D +n +n +t < @@ -66,7 +72,10 @@ P -Dnnt +D +n +n +t < @@ -74,7 +83,10 @@ P -Dnnt +D +n +n +t < diff --git a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-top-num-dunnet.svg b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-top-num-dunnet.svg index 4973b55..23a6c87 100644 --- a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-top-num-dunnet.svg +++ b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-top-num-dunnet.svg @@ -50,7 +50,10 @@ P -Dnnt +D +n +n +t = @@ -58,7 +61,10 @@ P -Dnnt +D +n +n +t < @@ -66,7 +72,10 @@ P -Dnnt +D +n +n +t < @@ -74,7 +83,10 @@ P -Dnnt +D +n +n +t < diff --git a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-top-num-letters-tukey.svg b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-top-num-letters-tukey.svg index e5a4fcb..a763058 100644 --- a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-top-num-letters-tukey.svg +++ b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-top-num-letters-tukey.svg @@ -47,14 +47,18 @@ - -P -HSD -crit - -= - -0.05 +P +H +S +D +c +r +i +t + += + +0.050 c c d diff --git a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-top-num-tukey.svg b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-top-num-tukey.svg index cff5860..1517b28 100644 --- a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-top-num-tukey.svg +++ b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-top-num-tukey.svg @@ -50,7 +50,9 @@ P -HSD +H +S +D = @@ -58,7 +60,9 @@ P -HSD +H +S +D < @@ -66,7 +70,9 @@ P -HSD +H +S +D < @@ -74,7 +80,9 @@ P -HSD +H +S +D < @@ -82,7 +90,9 @@ P -HSD +H +S +D = @@ -90,7 +100,9 @@ P -HSD +H +S +D < @@ -98,7 +110,9 @@ P -HSD +H +S +D < @@ -106,7 +120,9 @@ P -HSD +H +S +D = @@ -114,7 +130,9 @@ P -HSD +H +S +D < @@ -122,7 +140,9 @@ P -HSD +H +S +D = diff --git a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-top-tukey.svg b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-top-tukey.svg index ca14e4a..62b76fc 100644 --- a/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-top-tukey.svg +++ b/tests/testthat/_snaps/stat-multcomp/stat-multcomp-y-top-tukey.svg @@ -50,7 +50,9 @@ P -HSD +H +S +D = @@ -58,7 +60,9 @@ P -HSD +H +S +D < @@ -66,7 +70,9 @@ P -HSD +H +S +D < @@ -74,7 +80,9 @@ P -HSD +H +S +D < @@ -82,7 +90,9 @@ P -HSD +H +S +D = @@ -90,7 +100,9 @@ P -HSD +H +S +D < @@ -98,7 +110,9 @@ P -HSD +H +S +D < @@ -106,7 +120,9 @@ P -HSD +H +S +D = @@ -114,7 +130,9 @@ P -HSD +H +S +D < @@ -122,7 +140,9 @@ P -HSD +H +S +D = diff --git a/tests/testthat/_snaps/stat-poly-eq/stat-poly-eq-formula-1.svg b/tests/testthat/_snaps/stat-poly-eq/stat-poly-eq-formula-1.svg index f5f5ba4..4197d35 100644 --- a/tests/testthat/_snaps/stat-poly-eq/stat-poly-eq-formula-1.svg +++ b/tests/testthat/_snaps/stat-poly-eq/stat-poly-eq-formula-1.svg @@ -155,16 +155,16 @@ = -2807 - - -B -I -C - -= - -2812 +2807. + + +B +I +C + += + +2812. diff --git a/tests/testthat/_snaps/stat-poly-eq/stat-poly-eq-formula-x-round-inf.svg b/tests/testthat/_snaps/stat-poly-eq/stat-poly-eq-formula-x-round-inf.svg index 467a025..f48b5ec 100644 --- a/tests/testthat/_snaps/stat-poly-eq/stat-poly-eq-formula-x-round-inf.svg +++ b/tests/testthat/_snaps/stat-poly-eq/stat-poly-eq-formula-x-round-inf.svg @@ -171,8 +171,7 @@ 9.97 × 10 - -38 +−38 diff --git a/tests/testthat/_snaps/stat-poly-eq/stat-poly-eq-lm-chr.svg b/tests/testthat/_snaps/stat-poly-eq/stat-poly-eq-lm-chr.svg index 885eb42..2cd1ea5 100644 --- a/tests/testthat/_snaps/stat-poly-eq/stat-poly-eq-lm-chr.svg +++ b/tests/testthat/_snaps/stat-poly-eq/stat-poly-eq-lm-chr.svg @@ -196,16 +196,16 @@ = -2640 - - -B -I -C - -= - -2648 +2640. + + +B +I +C + += + +2648. diff --git a/tests/testthat/_snaps/stat-poly-eq/stat-poly-eq-lm-fun.svg b/tests/testthat/_snaps/stat-poly-eq/stat-poly-eq-lm-fun.svg index 7147089..d9042e0 100644 --- a/tests/testthat/_snaps/stat-poly-eq/stat-poly-eq-lm-fun.svg +++ b/tests/testthat/_snaps/stat-poly-eq/stat-poly-eq-lm-fun.svg @@ -196,16 +196,16 @@ = -2640 - - -B -I -C - -= - -2648 +2640. + + +B +I +C + += + +2648. diff --git a/tests/testthat/_snaps/stat-poly-eq/stat-poly-eq-noload-use-label.svg b/tests/testthat/_snaps/stat-poly-eq/stat-poly-eq-noload-use-label.svg index 16ff10b..1a7054d 100644 --- a/tests/testthat/_snaps/stat-poly-eq/stat-poly-eq-noload-use-label.svg +++ b/tests/testthat/_snaps/stat-poly-eq/stat-poly-eq-noload-use-label.svg @@ -153,16 +153,16 @@ = -2640 - - -B -I -C - -= - -2648 +2640. + + +B +I +C + += + +2648. diff --git a/tests/testthat/_snaps/stat-poly-eq/stat-poly-eq-noload.svg b/tests/testthat/_snaps/stat-poly-eq/stat-poly-eq-noload.svg index faaddf8..0f670e6 100644 --- a/tests/testthat/_snaps/stat-poly-eq/stat-poly-eq-noload.svg +++ b/tests/testthat/_snaps/stat-poly-eq/stat-poly-eq-noload.svg @@ -153,16 +153,16 @@ = -2640 - - -B -I -C - -= - -2648 +2640. + + +B +I +C + += + +2648. diff --git a/tests/testthat/_snaps/stat-poly-eq/stat-poly-eq-rlm-chr.svg b/tests/testthat/_snaps/stat-poly-eq/stat-poly-eq-rlm-chr.svg index ddcaf95..a54baaf 100644 --- a/tests/testthat/_snaps/stat-poly-eq/stat-poly-eq-rlm-chr.svg +++ b/tests/testthat/_snaps/stat-poly-eq/stat-poly-eq-rlm-chr.svg @@ -168,16 +168,16 @@ = -2641 - - -B -I -C - -= - -2649 +2641. + + +B +I +C + += + +2649. diff --git a/tests/testthat/_snaps/stat-poly-eq/stat-poly-eq-rlm-fun.svg b/tests/testthat/_snaps/stat-poly-eq/stat-poly-eq-rlm-fun.svg index 324bc35..9b70cf8 100644 --- a/tests/testthat/_snaps/stat-poly-eq/stat-poly-eq-rlm-fun.svg +++ b/tests/testthat/_snaps/stat-poly-eq/stat-poly-eq-rlm-fun.svg @@ -168,16 +168,16 @@ = -2641 - - -B -I -C - -= - -2649 +2641. + + +B +I +C + += + +2649. diff --git a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-1-round.svg b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-1-round.svg index 209ea63..b464841 100644 --- a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-1-round.svg +++ b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-1-round.svg @@ -127,69 +127,78 @@ -y - -= - -25.39 - - -ρ - -= - -987. - - -A -I -C - -= - -994.7 -y - -= - -53.83 - - -ρ - -= - -1.27e+03 - - -A -I -C - -= - -987.3 -y - -= - -73.19 - - -ρ - -= - -967. - - -A -I -C - -= - -990.6 +y + += + +25.39 + + +ρ + += + +9.9 +× +10 ++02 + + +A +I +C + += + +994.7 +y + += + +53.83 + + +ρ + += + +1.3 +× +10 ++03 + + +A +I +C + += + +987.3 +y + += + +73.19 + + +ρ + += + +9.7 +× +10 ++02 + + +A +I +C + += + +990.6 diff --git a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-1.svg b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-1.svg index b5e3e36..b2273cf 100644 --- a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-1.svg +++ b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-1.svg @@ -138,16 +138,16 @@ = -987. - - -A -I -C - -= - -994.7 +987.3 + + +A +I +C + += + +994.7 y = @@ -159,16 +159,16 @@ = -1.27e+03 - - -A -I -C - -= - -987.3 +1268. + + +A +I +C + += + +987.3 y = @@ -180,16 +180,16 @@ = -967. - - -A -I -C - -= - -990.6 +966.9 + + +A +I +C + += + +990.6 diff --git a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-1a.svg b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-1a.svg index 5e36216..341e624 100644 --- a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-1a.svg +++ b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-1a.svg @@ -138,16 +138,16 @@ = -987. - - -A -I -C - -= - -994.7 +987.3 + + +A +I +C + += + +994.7 y = @@ -159,16 +159,16 @@ = -1.27e+03 - - -A -I -C - -= - -987.3 +1268. + + +A +I +C + += + +987.3 y = @@ -180,16 +180,16 @@ = -967. - - -A -I -C - -= - -990.6 +966.9 + + +A +I +C + += + +990.6 diff --git a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-poly1.svg b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-poly1.svg index 2999608..dd297da 100644 --- a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-poly1.svg +++ b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-poly1.svg @@ -143,16 +143,16 @@ = -294. - - -A -I -C - -= - -754.7 +294.3 + + +A +I +C + += + +754.7 y = @@ -168,16 +168,16 @@ = -348. - - -A -I -C - -= - -730.6 +347.9 + + +A +I +C + += + +730.6 y = @@ -193,16 +193,16 @@ = -284. - - -A -I -C - -= - -747.5 +283.9 + + +A +I +C + += + +747.5 diff --git a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-poly3.svg b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-poly3.svg index dda004c..fc8c43e 100644 --- a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-poly3.svg +++ b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-poly3.svg @@ -157,16 +157,16 @@ = -291. - - -A -I -C - -= - -756.8 +291.5 + + +A +I +C + += + +756.8 y = @@ -197,16 +197,16 @@ = -345. - - -A -I -C - -= - -733 +345.1 + + +A +I +C + += + +733.0 y = @@ -236,16 +236,16 @@ = -282. - - -A -I -C - -= - -750 +281.8 + + +A +I +C + += + +750.0 diff --git a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-x-ix.svg b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-x-ix.svg index 3088499..25ad16f 100644 --- a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-x-ix.svg +++ b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-x-ix.svg @@ -143,16 +143,16 @@ = -294. - - -A -I -C - -= - -754.7 +294.3 + + +A +I +C + += + +754.7 y = @@ -168,16 +168,16 @@ = -348. - - -A -I -C - -= - -730.6 +347.9 + + +A +I +C + += + +730.6 y = @@ -193,16 +193,16 @@ = -284. - - -A -I -C - -= - -747.5 +283.9 + + +A +I +C + += + +747.5 diff --git a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-x-iy.svg b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-x-iy.svg index b30c23c..eb046de 100644 --- a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-x-iy.svg +++ b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-x-iy.svg @@ -143,16 +143,16 @@ = -294. - - -A -I -C - -= - -754.7 +294.3 + + +A +I +C + += + +754.7 y = @@ -168,16 +168,16 @@ = -348. - - -A -I -C - -= - -730.6 +347.9 + + +A +I +C + += + +730.6 y = @@ -193,16 +193,16 @@ = -284. - - -A -I -C - -= - -747.5 +283.9 + + +A +I +C + += + +747.5 diff --git a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-x.svg b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-x.svg index dd264a9..3b1a311 100644 --- a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-x.svg +++ b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-x.svg @@ -143,16 +143,16 @@ = -294. - - -A -I -C - -= - -754.7 +294.3 + + +A +I +C + += + +754.7 y = @@ -168,16 +168,16 @@ = -348. - - -A -I -C - -= - -730.6 +347.9 + + +A +I +C + += + +730.6 y = @@ -193,16 +193,16 @@ = -284. - - -A -I -C - -= - -747.5 +283.9 + + +A +I +C + += + +747.5 diff --git a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-x1.svg b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-x1.svg index 61e8d65..3217e67 100644 --- a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-x1.svg +++ b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-x1.svg @@ -138,16 +138,16 @@ = -938. - - -A -I -C - -= - -984.4 +937.5 + + +A +I +C + += + +984.4 x = @@ -159,16 +159,16 @@ = -1.25e+03 - - -A -I -C - -= - -984.4 +1250. + + +A +I +C + += + +984.4 x = @@ -180,16 +180,16 @@ = -938. - - -A -I -C - -= - -984.4 +937.5 + + +A +I +C + += + +984.4 diff --git a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-xminus1.svg b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-xminus1.svg index dab25a1..608aef0 100644 --- a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-xminus1.svg +++ b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-xminus1.svg @@ -140,16 +140,16 @@ = -300. - - -A -I -C - -= - -756.3 +299.7 + + +A +I +C + += + +756.3 y = @@ -163,16 +163,16 @@ = -348. - - -A -I -C - -= - -728.7 +348.0 + + +A +I +C + += + +728.7 y = @@ -186,16 +186,16 @@ = -300. - - -A -I -C - -= - -756.3 +299.6 + + +A +I +C + += + +756.3 diff --git a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-xminus1a.svg b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-xminus1a.svg index 539f993..36f3fc0 100644 --- a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-xminus1a.svg +++ b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-xminus1a.svg @@ -140,16 +140,16 @@ = -300. - - -A -I -C - -= - -756.3 +299.7 + + +A +I +C + += + +756.3 y = @@ -163,16 +163,16 @@ = -348. - - -A -I -C - -= - -728.7 +348.0 + + +A +I +C + += + +728.7 y = @@ -186,16 +186,16 @@ = -300. - - -A -I -C - -= - -756.3 +299.6 + + +A +I +C + += + +756.3 diff --git a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-xminus1b.svg b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-xminus1b.svg index 12eb5b4..d79e7d8 100644 --- a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-xminus1b.svg +++ b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-xminus1b.svg @@ -140,16 +140,16 @@ = -300. - - -A -I -C - -= - -756.3 +299.7 + + +A +I +C + += + +756.3 y = @@ -163,16 +163,16 @@ = -348. - - -A -I -C - -= - -728.7 +348.0 + + +A +I +C + += + +728.7 y = @@ -186,16 +186,16 @@ = -300. - - -A -I -C - -= - -756.3 +299.6 + + +A +I +C + += + +756.3 diff --git a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-xplus0.svg b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-xplus0.svg index fe78e05..cf30959 100644 --- a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-xplus0.svg +++ b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-xplus0.svg @@ -140,16 +140,16 @@ = -300. - - -A -I -C - -= - -756.3 +299.7 + + +A +I +C + += + +756.3 y = @@ -163,16 +163,16 @@ = -348. - - -A -I -C - -= - -728.7 +348.0 + + +A +I +C + += + +728.7 y = @@ -186,16 +186,16 @@ = -300. - - -A -I -C - -= - -756.3 +299.6 + + +A +I +C + += + +756.3 diff --git a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-xplus0a.svg b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-xplus0a.svg index 23a0378..06e0c28 100644 --- a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-xplus0a.svg +++ b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-xplus0a.svg @@ -140,16 +140,16 @@ = -300. - - -A -I -C - -= - -756.3 +299.7 + + +A +I +C + += + +756.3 y = @@ -163,16 +163,16 @@ = -348. - - -A -I -C - -= - -728.7 +348.0 + + +A +I +C + += + +728.7 y = @@ -186,16 +186,16 @@ = -300. - - -A -I -C - -= - -756.3 +299.6 + + +A +I +C + += + +756.3 diff --git a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-xplus0b.svg b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-xplus0b.svg index 8fc8429..7cdb3ae 100644 --- a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-xplus0b.svg +++ b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-xplus0b.svg @@ -140,16 +140,16 @@ = -300. - - -A -I -C - -= - -756.3 +299.7 + + +A +I +C + += + +756.3 y = @@ -163,16 +163,16 @@ = -348. - - -A -I -C - -= - -728.7 +348.0 + + +A +I +C + += + +728.7 y = @@ -186,16 +186,16 @@ = -300. - - -A -I -C - -= - -756.3 +299.6 + + +A +I +C + += + +756.3 diff --git a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-y-ix.svg b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-y-ix.svg index f9b96ae..3abbfe1 100644 --- a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-y-ix.svg +++ b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-y-ix.svg @@ -143,16 +143,16 @@ = -262. - - -A -I -C - -= - -731.1 +261.5 + + +A +I +C + += + +731.1 x = @@ -168,16 +168,16 @@ = -333. - - -A -I -C - -= - -721.8 +332.9 + + +A +I +C + += + +721.8 x = @@ -193,16 +193,16 @@ = -284. - - -A -I -C - -= - -747.4 +283.8 + + +A +I +C + += + +747.4 diff --git a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-y-iy.svg b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-y-iy.svg index 9dd511c..6ead72f 100644 --- a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-y-iy.svg +++ b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-y-iy.svg @@ -143,16 +143,16 @@ = -262. - - -A -I -C - -= - -731.1 +261.5 + + +A +I +C + += + +731.1 x = @@ -168,16 +168,16 @@ = -333. - - -A -I -C - -= - -721.8 +332.9 + + +A +I +C + += + +721.8 x = @@ -193,16 +193,16 @@ = -284. - - -A -I -C - -= - -747.4 +283.8 + + +A +I +C + += + +747.4 diff --git a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-y.svg b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-y.svg index 326aa56..6a054d3 100644 --- a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-y.svg +++ b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-y.svg @@ -143,16 +143,16 @@ = -262. - - -A -I -C - -= - -731.1 +261.5 + + +A +I +C + += + +731.1 x = @@ -168,16 +168,16 @@ = -333. - - -A -I -C - -= - -721.8 +332.9 + + +A +I +C + += + +721.8 x = @@ -193,16 +193,16 @@ = -284. - - -A -I -C - -= - -747.4 +283.8 + + +A +I +C + += + +747.4 diff --git a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-yminus1.svg b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-yminus1.svg index 94488a5..c92adc4 100644 --- a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-yminus1.svg +++ b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-yminus1.svg @@ -140,16 +140,16 @@ = -263. - - -A -I -C - -= - -730 +262.8 + + +A +I +C + += + +730.0 x = @@ -163,16 +163,16 @@ = -340. - - -A -I -C - -= - -723.8 +339.7 + + +A +I +C + += + +723.8 x = @@ -186,16 +186,16 @@ = -316. - - -A -I -C - -= - -766.8 +315.9 + + +A +I +C + += + +766.8 diff --git a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-yplus0.svg b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-yplus0.svg index c633798..288947c 100644 --- a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-yplus0.svg +++ b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-yplus0.svg @@ -140,16 +140,16 @@ = -263. - - -A -I -C - -= - -730 +262.8 + + +A +I +C + += + +730.0 x = @@ -163,16 +163,16 @@ = -340. - - -A -I -C - -= - -723.8 +339.7 + + +A +I +C + += + +723.8 x = @@ -186,16 +186,16 @@ = -316. - - -A -I -C - -= - -766.8 +315.9 + + +A +I +C + += + +766.8 diff --git a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-ypoly1.svg b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-ypoly1.svg index 5ff1f90..8e66cbd 100644 --- a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-ypoly1.svg +++ b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-formula-ypoly1.svg @@ -143,16 +143,16 @@ = -262. - - -A -I -C - -= - -731.1 +261.5 + + +A +I +C + += + +731.1 x = @@ -168,16 +168,16 @@ = -333. - - -A -I -C - -= - -721.8 +332.9 + + +A +I +C + += + +721.8 x = @@ -193,16 +193,16 @@ = -284. - - -A -I -C - -= - -747.4 +283.8 + + +A +I +C + += + +747.4 diff --git a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-noload-use-label.svg b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-noload-use-label.svg index 28b4e11..d347d9d 100644 --- a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-noload-use-label.svg +++ b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-noload-use-label.svg @@ -150,19 +150,19 @@ = -294. - - -A -I -C - -= - -754.7 - - -method: rq:br +294.3 + + +A +I +C + += + +754.7 + + +method: rq:br q = @@ -185,19 +185,19 @@ = -348. - - -A -I -C - -= - -730.6 - - -method: rq:br +347.9 + + +A +I +C + += + +730.6 + + +method: rq:br q = @@ -220,19 +220,19 @@ = -284. - - -A -I -C - -= - -747.5 - - -method: rq:br +283.9 + + +A +I +C + += + +747.5 + + +method: rq:br diff --git a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-noload.svg b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-noload.svg index 7196f1a..a37032b 100644 --- a/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-noload.svg +++ b/tests/testthat/_snaps/stat-quant-eq/stat-quant-eq-noload.svg @@ -143,19 +143,19 @@ = -294. - - -A -I -C - -= - -754.7 - - -method: rq:br +294.3 + + +A +I +C + += + +754.7 + + +method: rq:br y = @@ -171,19 +171,19 @@ = -348. - - -A -I -C - -= - -730.6 - - -method: rq:br +347.9 + + +A +I +C + += + +730.6 + + +method: rq:br y = @@ -199,19 +199,19 @@ = -284. - - -A -I -C - -= - -747.5 - - -method: rq:br +283.9 + + +A +I +C + += + +747.5 + + +method: rq:br diff --git a/tests/testthat/test-stat-quant-eq.R b/tests/testthat/test-stat-quant-eq.R index e2318ff..17d7111 100644 --- a/tests/testthat/test-stat-quant-eq.R +++ b/tests/testthat/test-stat-quant-eq.R @@ -38,8 +38,8 @@ test_that("quant_eq_noload", { ggplot2::ggplot(my.data, ggplot2::aes(x, y)) + ggplot2::geom_point() + ggpmisc::stat_quant_eq(formula = y ~ x, parse = TRUE, - mapping = ggpmisc::use_label(c("grp", "eq", "rho", "AIC", "method"), - ggplot2::aes(colour = ggplot2::after_stat(grp.label)), + mapping = ggpmisc::use_label(c("qtl", "eq", "rho", "AIC", "method"), + ggplot2::aes(colour = ggplot2::after_stat(qtl.label)), sep = "~~")) ) }, warning=function(w) { diff --git a/vignettes/model-based-annotations.R b/vignettes/model-based-annotations.R index 027bfb2..27199d0 100644 --- a/vignettes/model-based-annotations.R +++ b/vignettes/model-based-annotations.R @@ -147,7 +147,8 @@ formula <- y ~ poly(x, 3, raw = TRUE) ggplot(my.data, aes(x, y)) + geom_point() + stat_poly_line(formula = formula) + - stat_poly_eq(aes(label = paste("atop(", after_stat(AIC.label), ",", after_stat(BIC.label), ")", sep = "")), + stat_poly_eq(aes(label = paste("atop(", after_stat(AIC.label), ",", + after_stat(BIC.label), ")", sep = "")), formula = formula) ## ----eval=eval_flag----------------------------------------------------------- @@ -360,7 +361,7 @@ ggplot(my.data, aes(x, y)) + ggplot(my.data, aes(x, y)) + geom_point() + stat_quant_band(formula = formula, color = "black", fill = "grey60") + - stat_quant_eq(aes(label = paste(after_stat(grp.label), "*\": \"*", + stat_quant_eq(aes(label = paste(after_stat(qtl.label), "*\": \"*", after_stat(eq.label), sep = "")), formula = formula) + theme_classic() @@ -369,7 +370,7 @@ ggplot(my.data, aes(x, y)) + ggplot(my.data, aes(x, y, color = group)) + geom_point() + stat_quant_line(formula = formula) + - stat_quant_eq(aes(label = paste(after_stat(grp.label), "*\": \"*", + stat_quant_eq(aes(label = paste(after_stat(qtl.label), "*\": \"*", after_stat(eq.label), sep = "")), formula = formula) @@ -378,7 +379,8 @@ ggplot(my.data, aes(x, y, group = group, linetype = group, shape = group, grp.label = group)) + geom_point() + stat_quant_line(formula = formula, quantiles = c(0.05, 0.95), color = "black") + - stat_quant_eq(aes(label = paste(after_stat(grp.label), "*\": \"*", + stat_quant_eq(aes(label = paste(after_stat(grp.label), "*\", \"*", + after_stat(qtl.label), "*\": \"*", after_stat(eq.label), sep = "")), formula = formula, quantiles = c(0.05, 0.95)) + theme_classic() diff --git a/vignettes/model-based-annotations.Rmd b/vignettes/model-based-annotations.Rmd index 826568b..7b83579 100644 --- a/vignettes/model-based-annotations.Rmd +++ b/vignettes/model-based-annotations.Rmd @@ -426,7 +426,8 @@ formula <- y ~ poly(x, 3, raw = TRUE) ggplot(my.data, aes(x, y)) + geom_point() + stat_poly_line(formula = formula) + - stat_poly_eq(aes(label = paste("atop(", after_stat(AIC.label), ",", after_stat(BIC.label), ")", sep = "")), + stat_poly_eq(aes(label = paste("atop(", after_stat(AIC.label), ",", + after_stat(BIC.label), ")", sep = "")), formula = formula) ``` @@ -734,7 +735,7 @@ With `stat_quant_eq()` we add the fitted equations to the first example in this ggplot(my.data, aes(x, y)) + geom_point() + stat_quant_band(formula = formula, color = "black", fill = "grey60") + - stat_quant_eq(aes(label = paste(after_stat(grp.label), "*\": \"*", + stat_quant_eq(aes(label = paste(after_stat(qtl.label), "*\": \"*", after_stat(eq.label), sep = "")), formula = formula) + theme_classic() @@ -746,7 +747,7 @@ Grouping and faceting are supported by `stat_quant_eq()`, `stat_quant_line()` an ggplot(my.data, aes(x, y, color = group)) + geom_point() + stat_quant_line(formula = formula) + - stat_quant_eq(aes(label = paste(after_stat(grp.label), "*\": \"*", + stat_quant_eq(aes(label = paste(after_stat(qtl.label), "*\": \"*", after_stat(eq.label), sep = "")), formula = formula) ``` @@ -758,7 +759,8 @@ ggplot(my.data, aes(x, y, group = group, linetype = group, shape = group, grp.label = group)) + geom_point() + stat_quant_line(formula = formula, quantiles = c(0.05, 0.95), color = "black") + - stat_quant_eq(aes(label = paste(after_stat(grp.label), "*\": \"*", + stat_quant_eq(aes(label = paste(after_stat(grp.label), "*\", \"*", + after_stat(qtl.label), "*\": \"*", after_stat(eq.label), sep = "")), formula = formula, quantiles = c(0.05, 0.95)) + theme_classic() diff --git a/vignettes/model-based-annotations.html b/vignettes/model-based-annotations.html index d7117e3..fff8f11 100644 --- a/vignettes/model-based-annotations.html +++ b/vignettes/model-based-annotations.html @@ -12,7 +12,7 @@ - + Fitted-Model-Based Annotations @@ -339,9 +339,9 @@

Fitted-Model-Based Annotations

-

‘ggpmisc’ 0.5.5.9003

+

‘ggpmisc’ 0.5.6.9001

Pedro J. Aphalo

-

2024-05-05

+

2024-05-13

@@ -1849,8 +1849,9 @@

stat_poly_eq() and stat_poly_line()

ggplot(my.data, aes(x, y)) + geom_point() + stat_poly_line(formula = formula) + - stat_poly_eq(aes(label = paste("atop(", after_stat(AIC.label), ",", after_stat(BIC.label), ")", sep = "")), - formula = formula)
+ stat_poly_eq(aes(label = paste("atop(", after_stat(AIC.label), ",", + after_stat(BIC.label), ")", sep = "")), + formula = formula)

Next, one example of how to remove the left hand side (lhs).

@@ -2218,7 +2219,7 @@

stat_quant_eq(), stat_quant_line() and stat_quant_band()

ggplot(my.data, aes(x, y)) +
   geom_point() +
   stat_quant_band(formula = formula, color = "black", fill = "grey60") +
-  stat_quant_eq(aes(label = paste(after_stat(grp.label), "*\": \"*",
+  stat_quant_eq(aes(label = paste(after_stat(qtl.label), "*\": \"*",
                                   after_stat(eq.label), sep = "")),
                 formula = formula) +
   theme_classic()
@@ -2229,7 +2230,7 @@

stat_quant_eq(), stat_quant_line() and stat_quant_band()

ggplot(my.data, aes(x, y, color = group)) +
   geom_point() +
   stat_quant_line(formula = formula) +
-  stat_quant_eq(aes(label = paste(after_stat(grp.label), "*\": \"*",
+  stat_quant_eq(aes(label = paste(after_stat(qtl.label), "*\": \"*",
                                   after_stat(eq.label), sep = "")),
                formula = formula)

@@ -2239,10 +2240,11 @@

stat_quant_eq(), stat_quant_line() and stat_quant_band()

shape = group, grp.label = group)) + geom_point() + stat_quant_line(formula = formula, quantiles = c(0.05, 0.95), color = "black") + - stat_quant_eq(aes(label = paste(after_stat(grp.label), "*\": \"*", - after_stat(eq.label), sep = "")), - formula = formula, quantiles = c(0.05, 0.95)) + - theme_classic() + stat_quant_eq(aes(label = paste(after_stat(grp.label), "*\", \"*", + after_stat(qtl.label), "*\": \"*", + after_stat(eq.label), sep = "")), + formula = formula, quantiles = c(0.05, 0.95)) + + theme_classic()

In some cases double quantile regression is an informative method to assess reciprocal constraints. For this a fit of x on @@ -2285,112 +2287,139 @@

stat_multcomp

adj.method.tag = 3, size = 2.75) + expand_limits(y = 0) -

+
## Warning: Computation failed in `stat_multcomp()`.
+## Caused by error in `compute_panel()`:
+## ! object 'tstat.char' not found
+

Here we use a negative value to use an abbreviation of the word “adjusted” to three characters.

-
# position of contrasts' bars (manual)
-ggplot(mpg, aes(factor(cyl), hwy)) +
-  geom_boxplot(width = 0.33)  +
-  stat_multcomp(p.adjust.method = "bonferroni", 
-                adj.method.tag = -3,
-                size = 2.75) +
-  expand_limits(y = 0)
-

-

A character string passed as argument is used as is, here to set the -tag in Spanish.

# position of contrasts' bars (manual)
 ggplot(mpg, aes(factor(cyl), hwy)) +
   geom_boxplot(width = 0.33)  +
-  stat_multcomp(adj.method.tag = "ajustada",
-                size = 2.75) +
-  expand_limits(y = 0)
-

+ stat_multcomp(p.adjust.method = "bonferroni", + adj.method.tag = -3, + size = 2.75) + + expand_limits(y = 0) +
## Warning: Computation failed in `stat_multcomp()`.
+## Caused by error in `compute_panel()`:
+## ! object 'tstat.char' not found
+

+

A character string passed as argument is used as is, here to set the +tag in Spanish.

+
# position of contrasts' bars (manual)
+ggplot(mpg, aes(factor(cyl), hwy)) +
+  geom_boxplot(width = 0.33)  +
+  stat_multcomp(adj.method.tag = "ajustada",
+                size = 2.75) +
+  expand_limits(y = 0)
+
## Warning: Computation failed in `stat_multcomp()`.
+## Caused by error in `compute_panel()`:
+## ! object 'tstat.char' not found
+

A numeric vector passed to label.y can be used to manually set the location of each label along the y axis.

-
# position of contrasts' bars (manual)
-ggplot(mpg, aes(factor(cyl), hwy)) +
-  geom_boxplot(width = 0.33)  +
-  stat_multcomp(label.y = c(7, 4, 1),
-                contrasts = "Dunnet",
-                size = 2.75) +
-  expand_limits(y = 0)
-

-
ggplot(mpg, aes(factor(cyl), hwy)) +
-  geom_boxplot(width = 0.33) +
-   stat_multcomp(label.y = 
-                   seq(from = 15, 
-                       by = -3, 
-                       length.out = 6),
-                 size = 2.5) +
-   expand_limits(y = 0)
-

+
# position of contrasts' bars (manual)
+ggplot(mpg, aes(factor(cyl), hwy)) +
+  geom_boxplot(width = 0.33)  +
+  stat_multcomp(label.y = c(7, 4, 1),
+                contrasts = "Dunnet",
+                size = 2.75) +
+  expand_limits(y = 0)
+
## Warning: Computation failed in `stat_multcomp()`.
+## Caused by error in `compute_panel()`:
+## ! object 'tstat.char' not found
+

+
ggplot(mpg, aes(factor(cyl), hwy)) +
+  geom_boxplot(width = 0.33) +
+   stat_multcomp(label.y = 
+                   seq(from = 15, 
+                       by = -3, 
+                       length.out = 6),
+                 size = 2.5) +
+   expand_limits(y = 0)
+
## Warning: Computation failed in `stat_multcomp()`.
+## Caused by error in `compute_panel()`:
+## ! object 'tstat.char' not found
+

We can pre-compute the numeric vector to achieve special positioning, in this case, next to each observation.

-
means <-
-  aggregate(mpg$hwy,
-            by = list(mpg$cyl), 
-            FUN = mean, 
-            na.rm = TRUE)[["x"]]
-
-ggplot(mpg, aes(factor(cyl), hwy)) +
-  stat_summary(fun.data = mean_se) +
-  stat_multcomp(label.type = "letters",
-                label.y = c(18, means), # 18 is for critical P label
-                position = position_nudge(x = 0.1))
-

+
means <-
+  aggregate(mpg$hwy,
+            by = list(mpg$cyl), 
+            FUN = mean, 
+            na.rm = TRUE)[["x"]]
+
+ggplot(mpg, aes(factor(cyl), hwy)) +
+  stat_summary(fun.data = mean_se) +
+  stat_multcomp(label.type = "letters",
+                label.y = c(18, means), # 18 is for critical P label
+                position = position_nudge(x = 0.1))
+

We can override the default use of geom_text() and also remove the P critical label.

-
# Using other geometries
-ggplot(mpg, aes(factor(cyl), hwy)) +
-  geom_boxplot(width = 0.33) +
-  stat_multcomp(label.type = "letters",
-                adj.method.tag = FALSE,
-                geom = "label")
+
# Using other geometries
+ggplot(mpg, aes(factor(cyl), hwy)) +
+  geom_boxplot(width = 0.33) +
+  stat_multcomp(label.type = "letters",
+                adj.method.tag = FALSE,
+                geom = "label")

With Dunnet contrasts, the use of bars can clutter a plot, and we can alternatively show the outcome for each level that has been compared to a control, the first level.

-
ggplot(mpg, aes(factor(cyl), hwy)) +
-  geom_boxplot(width = 0.33) +
-  stat_multcomp(aes(x = stage(start = factor(cyl),
-                              after_stat = x.right.tip)),
-                geom = "text",
-                label.y = "bottom",
-                vstep = 0,
-                contrasts = "Dunnet")
-

-
ggplot(mpg, aes(factor(cyl), hwy)) +
-  geom_boxplot(width = 0.33) +
-  stat_multcomp(aes(x = stage(start = factor(cyl),
-                              after_stat = x.right.tip),
-                    label = after_stat(stars.label)),
-                geom = "text",
-                label.y = "bottom",
-                vstep = 0,
-                contrasts = "Dunnet")
-

+
ggplot(mpg, aes(factor(cyl), hwy)) +
+  geom_boxplot(width = 0.33) +
+  stat_multcomp(aes(x = stage(start = factor(cyl),
+                              after_stat = x.right.tip)),
+                geom = "text",
+                label.y = "bottom",
+                vstep = 0,
+                contrasts = "Dunnet")
+
## Warning: Computation failed in `stat_multcomp()`.
+## Caused by error in `compute_panel()`:
+## ! object 'tstat.char' not found
+

+
ggplot(mpg, aes(factor(cyl), hwy)) +
+  geom_boxplot(width = 0.33) +
+  stat_multcomp(aes(x = stage(start = factor(cyl),
+                              after_stat = x.right.tip),
+                    label = after_stat(stars.label)),
+                geom = "text",
+                label.y = "bottom",
+                vstep = 0,
+                contrasts = "Dunnet")
+
## Warning: Computation failed in `stat_multcomp()`.
+## Caused by error in `compute_panel()`:
+## ! object 'tstat.char' not found
+

The returned value includes numeric values in addition to character strings mapped to the label aesthetic. The numeric values can be used to encode the outcomes using additional or different aesthetics than the default.

-
# use colour to show significance
-ggplot(mpg, aes(factor(cyl), hwy)) +
-  geom_boxplot(width = 0.33) +
-  stat_multcomp(aes(colour = after_stat(p.value) < 0.01),
-                size = 2.75) +
-  scale_colour_manual(values = c("grey60", "black")) +
-  theme_bw()
-

-
# add arrow heads to segments and use fill to show significance
-ggplot(mpg, aes(factor(cyl), hwy)) +
-  geom_boxplot(width = 0.33) +
-  stat_multcomp(aes(fill = after_stat(p.value) < 0.01),
-                size = 2.5,
-                arrow = grid::arrow(angle = 45,
-                                    length = unit(1, "mm"),
-                                    ends = "both")) +
-  scale_fill_manual(values = c("white", "lightblue"))
-

+
# use colour to show significance
+ggplot(mpg, aes(factor(cyl), hwy)) +
+  geom_boxplot(width = 0.33) +
+  stat_multcomp(aes(colour = after_stat(p.value) < 0.01),
+                size = 2.75) +
+  scale_colour_manual(values = c("grey60", "black")) +
+  theme_bw()
+
## Warning: Computation failed in `stat_multcomp()`.
+## Caused by error in `compute_panel()`:
+## ! object 'tstat.char' not found
+

+
# add arrow heads to segments and use fill to show significance
+ggplot(mpg, aes(factor(cyl), hwy)) +
+  geom_boxplot(width = 0.33) +
+  stat_multcomp(aes(fill = after_stat(p.value) < 0.01),
+                size = 2.5,
+                arrow = grid::arrow(angle = 45,
+                                    length = unit(1, "mm"),
+                                    ends = "both")) +
+  scale_fill_manual(values = c("white", "lightblue"))
+
## Warning: Computation failed in `stat_multcomp()`.
+## Caused by error in `compute_panel()`:
+## ! object 'tstat.char' not found
+

stat_fit_residuals

@@ -2410,28 +2439,28 @@

stat_fit_residuals

by the residuals from the fit and thus also by default mapped to the aesthetic of the same name. The default geom is "point".

-
formula <- y ~ poly(x, 3, raw = TRUE)
-ggplot(my.data, aes(x, y, colour = group)) +
-  geom_hline(yintercept = 0, linetype = "dashed") +
-  stat_fit_residuals(formula = formula)
+
formula <- y ~ poly(x, 3, raw = TRUE)
+ggplot(my.data, aes(x, y, colour = group)) +
+  geom_hline(yintercept = 0, linetype = "dashed") +
+  stat_fit_residuals(formula = formula)

We can of course also map the weights returned in the model fit object to ggplot2 aesthetics, here we use size.

-
formula <- y ~ poly(x, 3, raw = TRUE)
-ggplot(my.data, aes(x, y, colour = group)) +
-  geom_hline(yintercept = 0, linetype = "dashed") +
-  stat_fit_residuals(formula = formula,
-                     method = "rlm",
-                     mapping = aes(size = sqrt(after_stat(weights))),
-                     alpha = 2/3)
+
formula <- y ~ poly(x, 3, raw = TRUE)
+ggplot(my.data, aes(x, y, colour = group)) +
+  geom_hline(yintercept = 0, linetype = "dashed") +
+  stat_fit_residuals(formula = formula,
+                     method = "rlm",
+                     mapping = aes(size = sqrt(after_stat(weights))),
+                     alpha = 2/3)

Weighted residuals are available, but in this case they do not differ as we have not mapped any variable to the weight aesthetic in the input to the statistic.

-
formula <- y ~ poly(x, 3, raw = TRUE)
-ggplot(my.data, aes(x, y, colour = group)) +
-  geom_hline(yintercept = 0, linetype = "dashed") +
-  stat_fit_residuals(formula = formula, weighted = TRUE)
+
formula <- y ~ poly(x, 3, raw = TRUE)
+ggplot(my.data, aes(x, y, colour = group)) +
+  geom_hline(yintercept = 0, linetype = "dashed") +
+  stat_fit_residuals(formula = formula, weighted = TRUE)

stat_fit_deviations

@@ -2445,36 +2474,36 @@

stat_fit_deviations

y, and the fitted values are mapped to aesthetics xend and yend. As the default geom is "segment", each deviation is displayed as a segment.

-
formula <- y ~ poly(x, 3, raw = TRUE)
-ggplot(my.data, aes(x, y)) +
-  geom_smooth(method = "lm", formula = formula) +
-  stat_fit_deviations(formula = formula, colour = "red") +
-  geom_point()
+
formula <- y ~ poly(x, 3, raw = TRUE)
+ggplot(my.data, aes(x, y)) +
+  geom_smooth(method = "lm", formula = formula) +
+  stat_fit_deviations(formula = formula, colour = "red") +
+  geom_point()

The geometry used by default is ggplot2::geom_segment() and additional aesthetics can be mapped or set to constant values. Here we add arrowheads.

-
formula <- y ~ poly(x, 3, raw = TRUE)
-ggplot(my.data, aes(x, y)) +
-  geom_smooth(method = "lm", formula = formula) +
-  geom_point() +
-  stat_fit_deviations(formula = formula, colour = "red",
-                      arrow = arrow(length = unit(0.015, "npc"), 
-                                   ends = "both"))
+
formula <- y ~ poly(x, 3, raw = TRUE)
+ggplot(my.data, aes(x, y)) +
+  geom_smooth(method = "lm", formula = formula) +
+  geom_point() +
+  stat_fit_deviations(formula = formula, colour = "red",
+                      arrow = arrow(length = unit(0.015, "npc"), 
+                                   ends = "both"))

When weights are available, either supplied by the user, or computed as part of the fit, they are returned in data. Having weights available allows encoding them using colour. We here use a robust regression fit with MASS::rlm().

-
my.data.outlier <- my.data
-my.data.outlier[6, "y"] <- my.data.outlier[6, "y"] * 5
-ggplot(my.data.outlier, aes(x, y)) +
-  stat_smooth(method = MASS::rlm, formula = formula) +
-  stat_fit_deviations(formula = formula, method = "rlm",
-                      mapping = aes(colour = after_stat(weights)),
-                      show.legend = TRUE) +
-  scale_color_gradient(low = "red", high = "blue", limits = c(0, 1)) +
-  geom_point()
+
my.data.outlier <- my.data
+my.data.outlier[6, "y"] <- my.data.outlier[6, "y"] * 5
+ggplot(my.data.outlier, aes(x, y)) +
+  stat_smooth(method = MASS::rlm, formula = formula) +
+  stat_fit_deviations(formula = formula, method = "rlm",
+                      mapping = aes(colour = after_stat(weights)),
+                      show.legend = TRUE) +
+  scale_color_gradient(low = "red", high = "blue", limits = c(0, 1)) +
+  geom_point()

@@ -2488,37 +2517,37 @@

stat_fit_glance

statistic in a plot with grouping, and assemble a label for the P-value using a string parsed into a expression. We also change the default position of the labels.

-
# formula <- y ~ poly(x, 3, raw = TRUE)
-# broom::augment does not handle poly() correctly!
-formula <- y ~ x + I(x^2) + I(x^3)
-ggplot(my.data, aes(x, y, colour = group)) +
-  geom_point() +
-  geom_smooth(method = "lm", formula = formula) +
-  stat_fit_glance(method = "lm", 
-                  method.args = list(formula = formula),
-                  label.x = "right",
-                  label.y = "bottom",
-                  aes(label = sprintf("italic(P)*\"-value = \"*%.3g", 
-                                      after_stat(p.value))),
-                  parse = TRUE)
+
# formula <- y ~ poly(x, 3, raw = TRUE)
+# broom::augment does not handle poly() correctly!
+formula <- y ~ x + I(x^2) + I(x^3)
+ggplot(my.data, aes(x, y, colour = group)) +
+  geom_point() +
+  geom_smooth(method = "lm", formula = formula) +
+  stat_fit_glance(method = "lm", 
+                  method.args = list(formula = formula),
+                  label.x = "right",
+                  label.y = "bottom",
+                  aes(label = sprintf("italic(P)*\"-value = \"*%.3g", 
+                                      after_stat(p.value))),
+                  parse = TRUE)

It is also possible to fit a non-linear model with method = "nls", and any other model for which a broom::glance() method exists. Do consult the documentation for package ‘broom’. Here we fit the Michaelis-Menten equation to reaction rate versus concentration data.

-
micmen.formula <- y ~ SSmicmen(x, Vm, K) 
-ggplot(Puromycin, aes(conc, rate, colour = state)) +
-  geom_point() +
-  geom_smooth(method = "nls", 
-              formula = micmen.formula,
-              se = FALSE) +
-  stat_fit_glance(method = "nls", 
-                  method.args = list(formula = micmen.formula),
-                  aes(label = paste("AIC = ", signif(after_stat(AIC), digits = 3), 
-                                    ", BIC = ", signif(after_stat(BIC), digits = 3),
-                                    sep = "")),
-                  label.x = "centre", label.y = "bottom")
+
micmen.formula <- y ~ SSmicmen(x, Vm, K) 
+ggplot(Puromycin, aes(conc, rate, colour = state)) +
+  geom_point() +
+  geom_smooth(method = "nls", 
+              formula = micmen.formula,
+              se = FALSE) +
+  stat_fit_glance(method = "nls", 
+                  method.args = list(formula = micmen.formula),
+                  aes(label = paste("AIC = ", signif(after_stat(AIC), digits = 3), 
+                                    ", BIC = ", signif(after_stat(BIC), digits = 3),
+                                    sep = "")),
+                  label.x = "centre", label.y = "bottom")

@@ -2540,106 +2569,106 @@

stat_fit_tb

The default output of stat_fit_tb() is the default output from tidy(fm) where fm is the fitted model.

-
formula <- y ~ x + I(x^2) + I(x^3)
-ggplot(my.data, aes(x, y)) +
-  geom_point() +
-  geom_smooth(method = "lm", formula = formula) +
-  stat_fit_tb(method = "lm",
-              method.args = list(formula = formula),
-              tb.vars = c(Parameter = "term", 
-                          Estimate = "estimate", 
-                          "s.e." = "std.error", 
-                          "italic(t)" = "statistic", 
-                          "italic(P)" = "p.value"),
-              label.y = "top", label.x = "left",
-              parse = TRUE)
+
formula <- y ~ x + I(x^2) + I(x^3)
+ggplot(my.data, aes(x, y)) +
+  geom_point() +
+  geom_smooth(method = "lm", formula = formula) +
+  stat_fit_tb(method = "lm",
+              method.args = list(formula = formula),
+              tb.vars = c(Parameter = "term", 
+                          Estimate = "estimate", 
+                          "s.e." = "std.error", 
+                          "italic(t)" = "statistic", 
+                          "italic(P)" = "p.value"),
+              label.y = "top", label.x = "left",
+              parse = TRUE)

When tb.type = "fit.anova" the output returned is that from tidy(anova(fm)) where fm is the fitted model. Here we also show how to replace names of columns and terms, and exclude one column, in this case, the mean squares.

-
formula <- y ~ x + I(x^2) + I(x^3)
-ggplot(my.data, aes(x, y)) +
-  geom_point() +
-  geom_smooth(method = "lm", formula = formula) +
-  stat_fit_tb(method = "lm",
-              method.args = list(formula = formula),
-              tb.type = "fit.anova",
-              tb.vars = c(Effect = "term", 
-                          df = "df",
-                          "italic(F)" = "statistic", 
-                          "italic(P)" = "p.value"),
-              tb.params = c(x = 1, "x^2" = 2, "x^3" = 3, Resid = 4),
-              label.y = "top", label.x = "left",
-              parse = TRUE)
+
formula <- y ~ x + I(x^2) + I(x^3)
+ggplot(my.data, aes(x, y)) +
+  geom_point() +
+  geom_smooth(method = "lm", formula = formula) +
+  stat_fit_tb(method = "lm",
+              method.args = list(formula = formula),
+              tb.type = "fit.anova",
+              tb.vars = c(Effect = "term", 
+                          df = "df",
+                          "italic(F)" = "statistic", 
+                          "italic(P)" = "p.value"),
+              tb.params = c(x = 1, "x^2" = 2, "x^3" = 3, Resid = 4),
+              label.y = "top", label.x = "left",
+              parse = TRUE)

When tb.type = "fit.coefs" the output returned is that of tidy(fm) after selecting the term and estimate columns.

-
formula <- y ~ x + I(x^2) + I(x^3)
-ggplot(my.data, aes(x, y)) +
-  geom_point() +
-  geom_smooth(method = "lm", formula = formula) +
-  stat_fit_tb(method = "lm",
-              method.args = list(formula = formula),
-              tb.type = "fit.coefs", parse = TRUE,
-              label.y = "center", label.x = "left")
+
formula <- y ~ x + I(x^2) + I(x^3)
+ggplot(my.data, aes(x, y)) +
+  geom_point() +
+  geom_smooth(method = "lm", formula = formula) +
+  stat_fit_tb(method = "lm",
+              method.args = list(formula = formula),
+              tb.type = "fit.coefs", parse = TRUE,
+              label.y = "center", label.x = "left")

Faceting works as expected, but grouping is ignored as mentioned above. In this case, the colour aesthetic is not applied to the text of the tables. Furthermore, if label.x.npc or label.y.npc are passed numeric vectors of length > 1, the corresponding values are obeyed by the different panels.

-
micmen.formula <- y ~ SSmicmen(x, Vm, K)
-ggplot(Puromycin, aes(conc, rate, colour = state)) +
-  facet_wrap(~state) +
-  geom_point() +
-  geom_smooth(method = "nls",
-              formula = micmen.formula,
-              se = FALSE) +
-  stat_fit_tb(method = "nls",
-              method.args = list(formula = micmen.formula),
-              tb.type = "fit.coefs",
-              label.x = 0.9,
-              label.y = c(0.75, 0.2)) +
-  theme(legend.position = "none") +
-  labs(x = "C", y = "V")
+
micmen.formula <- y ~ SSmicmen(x, Vm, K)
+ggplot(Puromycin, aes(conc, rate, colour = state)) +
+  facet_wrap(~state) +
+  geom_point() +
+  geom_smooth(method = "nls",
+              formula = micmen.formula,
+              se = FALSE) +
+  stat_fit_tb(method = "nls",
+              method.args = list(formula = micmen.formula),
+              tb.type = "fit.coefs",
+              label.x = 0.9,
+              label.y = c(0.75, 0.2)) +
+  theme(legend.position = "none") +
+  labs(x = "C", y = "V")

The data in the example below are split by ggplot into six groups based on the levels of the feed factor. However, as stat_fit_tb() ignores groupings, we can still fit a linear model to all the data in the panel.

-
ggplot(chickwts, aes(factor(feed), weight)) +
-  stat_summary(fun.data = "mean_se") +
-  stat_fit_tb(tb.type = "fit.anova",
-              label.x = "center",
-              label.y = "bottom") +
-  expand_limits(y = 0)
+
ggplot(chickwts, aes(factor(feed), weight)) +
+  stat_summary(fun.data = "mean_se") +
+  stat_fit_tb(tb.type = "fit.anova",
+              label.x = "center",
+              label.y = "bottom") +
+  expand_limits(y = 0)

We can flip the system of coordinates, if desired.

-
ggplot(chickwts, aes(factor(feed), weight)) +
-  stat_summary(fun.data = "mean_se") +
-  stat_fit_tb(tb.type = "fit.anova", label.x = "left", size = 3) +
-  scale_x_discrete(expand = expansion(mult = c(0.2, 0.5))) +
-  coord_flip()
+
ggplot(chickwts, aes(factor(feed), weight)) +
+  stat_summary(fun.data = "mean_se") +
+  stat_fit_tb(tb.type = "fit.anova", label.x = "left", size = 3) +
+  scale_x_discrete(expand = expansion(mult = c(0.2, 0.5))) +
+  coord_flip()

It is also possible to rotate the table using angle. Here we also show how to replace the column headers with strings to be parsed into R expressions.

-
ggplot(chickwts, aes(factor(feed), weight)) +
-  stat_summary(fun.data = "mean_se") +
-  stat_fit_tb(tb.type = "fit.anova",
-              angle = 90, size = 3,
-              label.x = "right", label.y = "center",
-              hjust = 0.5, vjust = 0,
-              tb.vars = c(Effect = "term", 
-                          "df",
-                          "M.S." = "meansq", 
-                          "italic(F)" = "statistic", 
-                          "italic(P)" = "p.value"),
-              parse = TRUE) +
-  scale_x_discrete(expand = expansion(mult = c(0.1, 0.35))) +
-  expand_limits(y = 0)
+
ggplot(chickwts, aes(factor(feed), weight)) +
+  stat_summary(fun.data = "mean_se") +
+  stat_fit_tb(tb.type = "fit.anova",
+              angle = 90, size = 3,
+              label.x = "right", label.y = "center",
+              hjust = 0.5, vjust = 0,
+              tb.vars = c(Effect = "term", 
+                          "df",
+                          "M.S." = "meansq", 
+                          "italic(F)" = "statistic", 
+                          "italic(P)" = "p.value"),
+              parse = TRUE) +
+  scale_x_discrete(expand = expansion(mult = c(0.1, 0.35))) +
+  expand_limits(y = 0)

@@ -2657,116 +2686,116 @@

stat_fit_tidy

equation of reaction kinetics, using stats::nls(). We use the self-starting function stats::SSmicmen() available in R.

-
micmen.formula <- y ~ SSmicmen(x, Vm, K) 
-ggplot(Puromycin, aes(conc, rate, colour = state)) +
-  geom_point() +
-  geom_smooth(method = "nls", 
-              formula = micmen.formula,
-              se = FALSE) +
-  stat_fit_tidy(method = "nls", 
-                method.args = list(formula = micmen.formula),
-                label.x = "right",
-                label.y = "bottom",
-                aes(label = paste("V[m]~`=`~", signif(after_stat(Vm_estimate), digits = 3),
-                                  "%+-%", signif(after_stat(Vm_se), digits = 2),
-                                  "~~~~K~`=`~", signif(after_stat(K_estimate), digits = 3),
-                                  "%+-%", signif(after_stat(K_se), digits = 2),
-                                  sep = "")),
-                parse = TRUE)
+
micmen.formula <- y ~ SSmicmen(x, Vm, K) 
+ggplot(Puromycin, aes(conc, rate, colour = state)) +
+  geom_point() +
+  geom_smooth(method = "nls", 
+              formula = micmen.formula,
+              se = FALSE) +
+  stat_fit_tidy(method = "nls", 
+                method.args = list(formula = micmen.formula),
+                label.x = "right",
+                label.y = "bottom",
+                aes(label = paste("V[m]~`=`~", signif(after_stat(Vm_estimate), digits = 3),
+                                  "%+-%", signif(after_stat(Vm_se), digits = 2),
+                                  "~~~~K~`=`~", signif(after_stat(K_estimate), digits = 3),
+                                  "%+-%", signif(after_stat(K_se), digits = 2),
+                                  sep = "")),
+                parse = TRUE)

Using paste we can build a string that can be parsed into an R expression, in this case for a non-linear equation.

-
micmen.formula <- y ~ SSmicmen(x, Vm, K) 
-ggplot(Puromycin, aes(conc, rate, colour = state)) +
-  geom_point() +
-  geom_smooth(method = "nls", 
-              formula = micmen.formula,
-              se = FALSE) +
-  stat_fit_tidy(method = "nls", 
-                method.args = list(formula = micmen.formula),
-                size = 3,
-                label.x = "center",
-                label.y = "bottom",
-                vstep = 0.12,
-                aes(label = paste("V~`=`~frac(", signif(after_stat(Vm_estimate), digits = 2), "~C,",
-                                  signif(after_stat(K_estimate), digits = 2), "+C)",
-                                  sep = "")),
-                parse = TRUE) +
-  labs(x = "C", y = "V")
+
micmen.formula <- y ~ SSmicmen(x, Vm, K) 
+ggplot(Puromycin, aes(conc, rate, colour = state)) +
+  geom_point() +
+  geom_smooth(method = "nls", 
+              formula = micmen.formula,
+              se = FALSE) +
+  stat_fit_tidy(method = "nls", 
+                method.args = list(formula = micmen.formula),
+                size = 3,
+                label.x = "center",
+                label.y = "bottom",
+                vstep = 0.12,
+                aes(label = paste("V~`=`~frac(", signif(after_stat(Vm_estimate), digits = 2), "~C,",
+                                  signif(after_stat(K_estimate), digits = 2), "+C)",
+                                  sep = "")),
+                parse = TRUE) +
+  labs(x = "C", y = "V")

What if we would need a more specific statistic, similar to stat_poly_eq()? We can use stat_fit_tidy() as the basis for its definition.

-
stat_micmen_eq <- function(vstep = 0.12,
-                           size = 3,
-                           ...) {
-  stat_fit_tidy(method = "nls", 
-                method.args = list(formula = micmen.formula),
-                aes(label = paste("V~`=`~frac(", signif(after_stat(Vm_estimate), digits = 2), "~C,",
-                                  signif(after_stat(K_estimate), digits = 2), "+C)",
-                                  sep = "")),
-                parse = TRUE,
-                vstep = vstep,
-                size = size,
-                ...)
-}
+
stat_micmen_eq <- function(vstep = 0.12,
+                           size = 3,
+                           ...) {
+  stat_fit_tidy(method = "nls", 
+                method.args = list(formula = micmen.formula),
+                aes(label = paste("V~`=`~frac(", signif(after_stat(Vm_estimate), digits = 2), "~C,",
+                                  signif(after_stat(K_estimate), digits = 2), "+C)",
+                                  sep = "")),
+                parse = TRUE,
+                vstep = vstep,
+                size = size,
+                ...)
+}

The code for the figure is now simpler, and still produces the same figure (not shown).

-
micmen.formula <- y ~ SSmicmen(x, Vm, K) 
-ggplot(Puromycin, aes(conc, rate, colour = state)) +
-  geom_point() +
-  geom_smooth(method = "nls", 
-              formula = micmen.formula,
-              se = FALSE) +
-  stat_micmen_eq(label.x = "center",
-                label.y = "bottom") +
-  labs(x = "C", y = "V")
+
micmen.formula <- y ~ SSmicmen(x, Vm, K) 
+ggplot(Puromycin, aes(conc, rate, colour = state)) +
+  geom_point() +
+  geom_smooth(method = "nls", 
+              formula = micmen.formula,
+              se = FALSE) +
+  stat_micmen_eq(label.x = "center",
+                label.y = "bottom") +
+  labs(x = "C", y = "V")

  • As a second example we show a quantile regression fit using function quantreg::rq() from package ‘quantreg’.
-
my_formula <- y ~ x
-
-ggplot(mpg, aes(displ, 1 / hwy)) +
-  geom_point() +
-  geom_quantile(quantiles = 0.5, formula = my_formula) +
-  stat_fit_tidy(method = "rq",
-                method.args = list(formula = y ~ x, tau = 0.5), 
-                tidy.args = list(se.type = "nid"),
-                mapping = aes(label = sprintf('y~"="~%.3g+%.3g~x*", with "*italic(P)~"="~%.3f',
-                                              after_stat(Intercept_estimate), 
-                                              after_stat(x_estimate),
-                                              after_stat(x_p.value))),
-                parse = TRUE)
+
my_formula <- y ~ x
+
+ggplot(mpg, aes(displ, 1 / hwy)) +
+  geom_point() +
+  geom_quantile(quantiles = 0.5, formula = my_formula) +
+  stat_fit_tidy(method = "rq",
+                method.args = list(formula = y ~ x, tau = 0.5), 
+                tidy.args = list(se.type = "nid"),
+                mapping = aes(label = sprintf('y~"="~%.3g+%.3g~x*", with "*italic(P)~"="~%.3f',
+                                              after_stat(Intercept_estimate), 
+                                              after_stat(x_estimate),
+                                              after_stat(x_p.value))),
+                parse = TRUE)

We can define a stat_rq_eq() if we need to add similar equations to several plots. In this example we retain the ability of the user to override most of the default default arguments.

-
stat_rq_eqn <- 
-  function(formula = y ~ x, 
-           tau = 0.5,
-           method = "br",
-           mapping = aes(label = sprintf('y~"="~%.3g+%.3g~x*", with "*italic(P)~"="~%.3f',
-                                         after_stat(Intercept_estimate), 
-                                         after_stat(x_estimate),
-                                         after_stat(x_p.value))),
-           parse = TRUE,
-           ...) {
-    method.args <- list(formula = formula, tau = tau, method = method)
-    stat_fit_tidy(method = "rq",
-                  method.args = method.args, 
-                  tidy.args = list(se.type = "nid"),
-                  mapping = mapping,
-                  parse = parse,
-                  ...)
-  }
+
stat_rq_eqn <- 
+  function(formula = y ~ x, 
+           tau = 0.5,
+           method = "br",
+           mapping = aes(label = sprintf('y~"="~%.3g+%.3g~x*", with "*italic(P)~"="~%.3f',
+                                         after_stat(Intercept_estimate), 
+                                         after_stat(x_estimate),
+                                         after_stat(x_p.value))),
+           parse = TRUE,
+           ...) {
+    method.args <- list(formula = formula, tau = tau, method = method)
+    stat_fit_tidy(method = "rq",
+                  method.args = method.args, 
+                  tidy.args = list(se.type = "nid"),
+                  mapping = mapping,
+                  parse = parse,
+                  ...)
+  }

And the code of the figure now as simple as. Figure not shown, as is identical to the one above.

-
ggplot(mpg, aes(displ, 1 / hwy)) +
-  geom_point() +
-  geom_quantile(quantiles = 0.5, formula = my_formula) +
-  stat_rq_eqn(tau = 0.5, formula = my_formula)
+
ggplot(mpg, aes(displ, 1 / hwy)) +
+  geom_point() +
+  geom_quantile(quantiles = 0.5, formula = my_formula) +
+  stat_rq_eqn(tau = 0.5, formula = my_formula)

@@ -2781,66 +2810,66 @@

stat_fit_augment

stat_fit_augment() can handle any fitted model that is supported by package ‘broom’ or its extensions. All these statistics support grouping and facets.

-
# formula <- y ~ poly(x, 3, raw = TRUE)
-# broom::augment does not handle poly correctly!
-formula <- y ~ x + I(x^2) + I(x^3)
-ggplot(my.data, aes(x, y)) +
-  geom_point() +
-  stat_fit_augment(method = "lm",
-                   method.args = list(formula = formula))
+
# formula <- y ~ poly(x, 3, raw = TRUE)
+# broom::augment does not handle poly correctly!
+formula <- y ~ x + I(x^2) + I(x^3)
+ggplot(my.data, aes(x, y)) +
+  geom_point() +
+  stat_fit_augment(method = "lm",
+                   method.args = list(formula = formula))

-
formula <- y ~ x + I(x^2) + I(x^3)
-ggplot(my.data, aes(x, y, colour = group)) +
-  geom_point() +
-  stat_fit_augment(method = "lm", 
-                   method.args = list(formula = formula))
+
formula <- y ~ x + I(x^2) + I(x^3)
+ggplot(my.data, aes(x, y, colour = group)) +
+  geom_point() +
+  stat_fit_augment(method = "lm", 
+                   method.args = list(formula = formula))

We can override the variable returned as y to be any of the variables in the data frame returned by broom::augment() while still preserving the original y values.

-
formula <- y ~ x + I(x^2) + I(x^3)
-ggplot(my.data, aes(x, y)) +
-  stat_fit_augment(method = "lm",
-                   method.args = list(formula = formula),
-                   geom = "point",
-                   y.out = ".resid")
+
formula <- y ~ x + I(x^2) + I(x^3)
+ggplot(my.data, aes(x, y)) +
+  stat_fit_augment(method = "lm",
+                   method.args = list(formula = formula),
+                   geom = "point",
+                   y.out = ".resid")

-
formula <- y ~ x + I(x^2) + I(x^3)
-ggplot(my.data, aes(x, y, colour = group)) +
-  stat_fit_augment(method = "lm",
-                   method.args = list(formula = formula),
-                   geom = "point",
-                   y.out = ".std.resid")
+
formula <- y ~ x + I(x^2) + I(x^3)
+ggplot(my.data, aes(x, y, colour = group)) +
+  stat_fit_augment(method = "lm",
+                   method.args = list(formula = formula),
+                   geom = "point",
+                   y.out = ".std.resid")

We can use any model fitting method for which broom::augment() is implemented.

-
args <- list(formula = y ~ k * e ^ x,
-             start = list(k = 1, e = 2))
-ggplot(mtcars, aes(wt, mpg)) +
-  geom_point() +
-  stat_fit_augment(method = "nls",
-                   method.args = args)
+
args <- list(formula = y ~ k * e ^ x,
+             start = list(k = 1, e = 2))
+ggplot(mtcars, aes(wt, mpg)) +
+  geom_point() +
+  stat_fit_augment(method = "nls",
+                   method.args = args)

-
args <- list(formula = y ~ k * e ^ x,
-             start = list(k = 1, e = 2))
-ggplot(mtcars, aes(wt, mpg)) +
-  stat_fit_augment(method = "nls",
-                   method.args = args,
-                   geom = "point",
-                   y.out = ".resid")
+
args <- list(formula = y ~ k * e ^ x,
+             start = list(k = 1, e = 2))
+ggplot(mtcars, aes(wt, mpg)) +
+  stat_fit_augment(method = "nls",
+                   method.args = args,
+                   geom = "point",
+                   y.out = ".resid")

Note: The tidiers for mixed models have moved to package ‘broom.mixed’!

-
args <- list(model = y ~ SSlogis(x, Asym, xmid, scal),
-             fixed = Asym + xmid + scal ~1,
-             random = Asym ~1 | group,
-             start = c(Asym = 200, xmid = 725, scal = 350))
-ggplot(Orange, aes(age, circumference, colour = Tree)) +
-  geom_point() +
-  stat_fit_augment(method = "nlme",
-                   method.args = args,
-                   augment.args = list(data = quote(data)))
+
args <- list(model = y ~ SSlogis(x, Asym, xmid, scal),
+             fixed = Asym + xmid + scal ~1,
+             random = Asym ~1 | group,
+             start = c(Asym = 200, xmid = 725, scal = 350))
+ggplot(Orange, aes(age, circumference, colour = Tree)) +
+  geom_point() +
+  stat_fit_augment(method = "nlme",
+                   method.args = args,
+                   augment.args = list(data = quote(data)))

@@ -2860,20 +2889,20 @@

How to find out what variables are computed

statistics or directly as a layer function. However, unrecognised aesthetics can trigger warnings during plot rendering. These warnings can be ignored in most cases.

-
# formula <- y ~ poly(x, 3, raw = TRUE)
-# broom::augment does not handle poly() correctly!
-formula <- y ~ x + I(x^2) + I(x^3)
-ggplot(my.data, aes(x, y, colour = group)) +
-  geom_point() +
-  geom_smooth(method = "lm", formula = formula) +
-  stat_fit_glance(geom = "debug",
-                  method = "lm", 
-                  method.args = list(formula = formula),
-                  label.x = "right",
-                  label.y = "bottom",
-                  aes(label = sprintf("italic(P)*\"-value = \"*%.3g", 
-                                      after_stat(p.value))),
-                  parse = TRUE)
+
# formula <- y ~ poly(x, 3, raw = TRUE)
+# broom::augment does not handle poly() correctly!
+formula <- y ~ x + I(x^2) + I(x^3)
+ggplot(my.data, aes(x, y, colour = group)) +
+  geom_point() +
+  geom_smooth(method = "lm", formula = formula) +
+  stat_fit_glance(geom = "debug",
+                  method = "lm", 
+                  method.args = list(formula = formula),
+                  label.x = "right",
+                  label.y = "bottom",
+                  aes(label = sprintf("italic(P)*\"-value = \"*%.3g", 
+                                      after_stat(p.value))),
+                  parse = TRUE)
## Warning in stat_fit_glance(geom = "debug", method = "lm", method.args =
 ## list(formula = formula), : Ignoring unknown parameters: `parse`
## [1] "PANEL 1; group(s) 1, 2; 'draw_function()' input 'data' (head):"
@@ -2895,21 +2924,21 @@ 

How to find out what variables are computed

case, function str() is more informative than head(), so we can pass it as argument overriding the default.

-
formula <- y ~ x + I(x^2) + I(x^3)
-ggplot(my.data, aes(x, y)) +
-  geom_point() +
-  geom_smooth(method = "lm", formula = formula) +
-  stat_fit_tb(geom = "debug",
-              summary.fun = str,
-              method = "lm",
-              method.args = list(formula = formula),
-              tb.vars = c(Parameter = "term", 
-                          Estimate = "estimate", 
-                          "s.e." = "std.error", 
-                          "italic(t)" = "statistic", 
-                          "italic(P)" = "p.value"),
-              label.y = "top", label.x = "left",
-              parse = TRUE)
+
formula <- y ~ x + I(x^2) + I(x^3)
+ggplot(my.data, aes(x, y)) +
+  geom_point() +
+  geom_smooth(method = "lm", formula = formula) +
+  stat_fit_tb(geom = "debug",
+              summary.fun = str,
+              method = "lm",
+              method.args = list(formula = formula),
+              tb.vars = c(Parameter = "term", 
+                          Estimate = "estimate", 
+                          "s.e." = "std.error", 
+                          "italic(t)" = "statistic", 
+                          "italic(P)" = "p.value"),
+              label.y = "top", label.x = "left",
+              parse = TRUE)
## Warning in stat_fit_tb(geom = "debug", summary.fun = str, method = "lm", : Ignoring unknown parameters: `table.theme`, `table.rownames`, `table.colnames`,
 ## `table.hjust`, `parse`, and `summary.fun`
## [1] "PANEL 1; group(s) NULL; 'draw_function()' input 'data' (head):"
@@ -2970,7 +2999,7 @@ 

Volcano-plot examples

Outcomes encoded as -1, 0 or 1, as seen in the tibble below need to be converted into factors with suitable labels for levels. This can be easily achieved with function outcome2factor().

-
head(volcano_example.df) 
+
head(volcano_example.df) 
##         tag     gene outcome       logFC     PValue genotype
 ## 1 AT1G01040     ASU1       0 -0.15284466 0.35266997      Ler
 ## 2 AT1G01290     ASG4       0 -0.30057068 0.05471732      Ler
@@ -2996,24 +3025,24 @@ 

Volcano-plot examples

arguments to parameters name and labels of these scales. These x and y scales by default squish off-limits (out-of-bounds) observations towards the limits.

-
ggplot(volcano_example.df, 
-       aes(logFC, PValue, colour = outcome2factor(outcome))) +
-  geom_point() +
-  scale_x_logFC(name = "Transcript abundance%unit") +
-  scale_y_Pvalue() +
-  scale_colour_outcome() +
-  stat_quadrant_counts(data = function(x) {subset(x, outcome != 0)})
+
ggplot(volcano_example.df, 
+       aes(logFC, PValue, colour = outcome2factor(outcome))) +
+  geom_point() +
+  scale_x_logFC(name = "Transcript abundance%unit") +
+  scale_y_Pvalue() +
+  scale_colour_outcome() +
+  stat_quadrant_counts(data = function(x) {subset(x, outcome != 0)})

By default outcome2factor() creates a factor with three levels as in the example above, but this default can be overridden as shown below.

-
ggplot(volcano_example.df, 
-       aes(logFC, PValue, colour = outcome2factor(outcome, n.levels = 2))) +
-  geom_point() +
-  scale_x_logFC(name = "Transcript abundance%unit") +
-  scale_y_Pvalue() +
-  scale_colour_outcome() +
-  stat_quadrant_counts(data = function(x) {subset(x, outcome != 0)})
+
ggplot(volcano_example.df, 
+       aes(logFC, PValue, colour = outcome2factor(outcome, n.levels = 2))) +
+  geom_point() +
+  scale_x_logFC(name = "Transcript abundance%unit") +
+  scale_y_Pvalue() +
+  scale_colour_outcome() +
+  stat_quadrant_counts(data = function(x) {subset(x, outcome != 0)})

@@ -3032,7 +3061,7 @@

Quadrant-plot examples

circle and map one of the outcomes to colour and the other to fill, using the two matched scales scale_colour_outcome() and scale_fill_outcome().

-
head(quadrant_example.df)
+
head(quadrant_example.df)
##         tag     gene outcome.x outcome.y     logFC.x     logFC.y genotype
 ## 1 AT5G11060    TIC56         0         0 -0.17685517 -0.32956762      Ler
 ## 2 AT3G01280 ATWRKY48         0         0 -0.06471884  0.07771315      Ler
@@ -3042,66 +3071,66 @@ 

Quadrant-plot examples

## 6 AT2G16070 UBQ11 0 0 -0.22328946 -0.23210780 Ler

In this plot we do not include those genes whose change in transcript abundance is uncertain under both x and y conditions.

-
  ggplot(subset(quadrant_example.df, 
-                xy_outcomes2factor(outcome.x, outcome.y) != "none"),
-         aes(logFC.x, logFC.y, 
-             colour = outcome2factor(outcome.x), 
-             fill = outcome2factor(outcome.y))) +
-  geom_quadrant_lines(linetype = "dotted") +
-  stat_quadrant_counts(size = 3, colour = "white") +
-  geom_point(shape = "circle filled") +
-  scale_x_logFC(name = "Transcript abundance for x%unit") +
-  scale_y_logFC(name = "Transcript abundance for y%unit") +
-  scale_colour_outcome() +
-  scale_fill_outcome() +
-  theme_dark()
+
  ggplot(subset(quadrant_example.df, 
+                xy_outcomes2factor(outcome.x, outcome.y) != "none"),
+         aes(logFC.x, logFC.y, 
+             colour = outcome2factor(outcome.x), 
+             fill = outcome2factor(outcome.y))) +
+  geom_quadrant_lines(linetype = "dotted") +
+  stat_quadrant_counts(size = 3, colour = "white") +
+  geom_point(shape = "circle filled") +
+  scale_x_logFC(name = "Transcript abundance for x%unit") +
+  scale_y_logFC(name = "Transcript abundance for y%unit") +
+  scale_colour_outcome() +
+  scale_fill_outcome() +
+  theme_dark()

To plot in separate panels those observations that are significant along both x and y axes, x axis, y axis, or none, with quadrants merged takes more effort. We first define two helper functions to add counts and quadrant lines to each of the four panels.

-
all_quadrant_counts <- function(...) {
-  list(  
-    stat_quadrant_counts(data = . %>% filter(outcome.xy.fct == "xy"), ...),
-    stat_quadrant_counts(data = . %>% filter(outcome.xy.fct == "x"), pool.along = "y", ...),
-    stat_quadrant_counts(data = . %>% filter(outcome.xy.fct == "y"), pool.along = "x", ...),
-    stat_quadrant_counts(data = . %>% filter(outcome.xy.fct == "none"), quadrants = 0L, ...)
-  )
-}
-
all_quadrant_lines <- function(...) { 
-  list(
-    geom_hline(data =  data.frame(outcome.xy.fct = factor(c("xy", "x", "y", "none"),
-                                                          levels = c("xy", "x", "y", "none")),
-                                  yintercept = c(0, NA, 0, NA)),
-               aes(yintercept = yintercept),
-               na.rm = TRUE,
-               ...),
-    geom_vline(data =  data.frame(outcome.xy.fct = factor(c("xy", "x", "y", "none"),
-                                                          levels = c("xy", "x", "y", "none")),
-                                  xintercept = c(0, 0, NA, NA)),
-               aes(xintercept = xintercept),
-               na.rm = TRUE,
-               ...)
-  )
-}
+
all_quadrant_counts <- function(...) {
+  list(  
+    stat_quadrant_counts(data = . %>% filter(outcome.xy.fct == "xy"), ...),
+    stat_quadrant_counts(data = . %>% filter(outcome.xy.fct == "x"), pool.along = "y", ...),
+    stat_quadrant_counts(data = . %>% filter(outcome.xy.fct == "y"), pool.along = "x", ...),
+    stat_quadrant_counts(data = . %>% filter(outcome.xy.fct == "none"), quadrants = 0L, ...)
+  )
+}
+
all_quadrant_lines <- function(...) { 
+  list(
+    geom_hline(data =  data.frame(outcome.xy.fct = factor(c("xy", "x", "y", "none"),
+                                                          levels = c("xy", "x", "y", "none")),
+                                  yintercept = c(0, NA, 0, NA)),
+               aes(yintercept = yintercept),
+               na.rm = TRUE,
+               ...),
+    geom_vline(data =  data.frame(outcome.xy.fct = factor(c("xy", "x", "y", "none"),
+                                                          levels = c("xy", "x", "y", "none")),
+                                  xintercept = c(0, 0, NA, NA)),
+               aes(xintercept = xintercept),
+               na.rm = TRUE,
+               ...)
+  )
+}

And use these functions to build the final plot, in this case including all genes.

-
quadrant_example.df %>%
-  mutate(.,
-         outcome.x.fct = outcome2factor(outcome.x),
-         outcome.y.fct = outcome2factor(outcome.y),
-         outcome.xy.fct = xy_outcomes2factor(outcome.x, outcome.y)) %>%
-  ggplot(., aes(logFC.x, logFC.y, colour = outcome.x.fct, fill = outcome.y.fct)) +
-  geom_point(shape = 21) +
-  all_quadrant_lines(linetype = "dotted") +
-  all_quadrant_counts(size = 3, colour = "white") +
-  scale_x_logFC(name = "Transcript abundance for x%unit") +
-  scale_y_logFC(name = "Transcript abundance for y%unit") +
-  scale_colour_outcome() +
-  scale_fill_outcome() +
-  facet_wrap(~outcome.xy.fct) +
-  theme_dark()
+
quadrant_example.df %>%
+  mutate(.,
+         outcome.x.fct = outcome2factor(outcome.x),
+         outcome.y.fct = outcome2factor(outcome.y),
+         outcome.xy.fct = xy_outcomes2factor(outcome.x, outcome.y)) %>%
+  ggplot(., aes(logFC.x, logFC.y, colour = outcome.x.fct, fill = outcome.y.fct)) +
+  geom_point(shape = 21) +
+  all_quadrant_lines(linetype = "dotted") +
+  all_quadrant_counts(size = 3, colour = "white") +
+  scale_x_logFC(name = "Transcript abundance for x%unit") +
+  scale_y_logFC(name = "Transcript abundance for y%unit") +
+  scale_colour_outcome() +
+  scale_fill_outcome() +
+  facet_wrap(~outcome.xy.fct) +
+  theme_dark()