Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

plot.parameters_simulate formatting VS parameters_model formatting #367

Merged
merged 6 commits into from
Sep 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Type: Package
Package: see
Title: Model Visualisation Toolbox for 'easystats' and 'ggplot2'
Version: 0.9.0.3
Version: 0.9.0.4
Authors@R:
c(person(given = "Daniel",
family = "Lüdecke",
Expand Down Expand Up @@ -93,6 +93,7 @@ Suggests:
lme4,
logspline,
MASS,
mclogit,
mclust,
merDeriv,
mgcv,
Expand Down
10 changes: 10 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@
- `plot()` for `model_parameters()` now also plots group-levels of random effects
(i.e. for mixed models, when `model_parameters(x, ..., group_level = TRUE)`).

- `plot()` for `model_parameters()` gets a `show_direction` argument, to turn
off the direction of the effect in the plot.

- `plot()` for `simulate_parameters()` now better copes with models that have
multiple response levels (e.g. multinomial models).

## Bug fixes

- Fixed issue in `plot()` for `parameters::model_parameters()` for GAM models.

# see 0.9.0

## Changes
Expand Down
50 changes: 44 additions & 6 deletions R/plot.parameters_model.R
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
#' @param show_density Should the compatibility density (i.e., posterior,
#' bootstrap, or confidence density) of each parameter be shown?
#' (default: `FALSE`)
#' @param show_direction Should the "direction" of coefficients (e.g., positive
#' or negative coefficients) be highlighted using different colors?
#' (default: `TRUE`)
#' @param log_scale Should exponentiated coefficients (e.g., odds-ratios) be
#' plotted on a log scale? (default: `FALSE`)
#' @param n_columns For models with multiple components (like fixed and random,
Expand All @@ -29,6 +32,14 @@
#'
#' @return A ggplot2-object.
#'
#' @note By default, coefficients and their confidence intervals are colored
#' depending on whether they show a "positive" or "negative" association with
#' the outcome. E.g., in case of linear models, colors simply distinguish positive
#' or negative coefficients. For logistic regression models that are shown on the
#' odds ratio scale, colors distinguish odds ratios above or below 1. Use
#' `show_direction = FALSE` to disable this feature and only show a one-colored
#' forest plot.
#'
#' @examples
#' library(parameters)
#' m <- lm(mpg ~ wt + cyl + gear + disp, data = mtcars)
Expand All @@ -36,7 +47,7 @@
#' result
#' plot(result)
#' @export
plot.see_parameters_model <- function(x,

Check warning on line 50 in R/plot.parameters_model.R

View workflow job for this annotation

GitHub Actions / lint-changed-files / lint-changed-files

file=R/plot.parameters_model.R,line=50,col=1,[cyclocomp_linter] Reduce the cyclomatic complexity of this function from 141 to at most 40.
show_intercept = FALSE,
size_point = 0.8,
size_text = NA,
Expand All @@ -48,11 +59,21 @@
show_estimate = TRUE,
show_interval = TRUE,
show_density = FALSE,
show_direction = TRUE,
log_scale = FALSE,
...) {
# retrieve settings ----------------
model_attributes <- attributes(x)[!names(attributes(x)) %in% c("names", "row.names", "class")]

# for GAMs, remove smooth terms
if (!is.null(x$Component) && any(x$Component == "smooth_terms")) {
x <- x[x$Component != "smooth_terms", ]
# if we only have one component left, remove Component column
if (insight::n_unique(x$Component) == 1) {
x$Component <- NULL
}
}

# user wants to plot random effects (group levels)?
if (isFALSE(model_attributes$ignore_group) &&
isTRUE(model_attributes$mixed_model) &&
Expand All @@ -70,7 +91,7 @@

# Clean up column names
if (!any(grepl("Coefficient", colnames(x), fixed = TRUE))) {
colnames(x)[which.min(match(colnames(x), c("Median", "Mean", "Map", "MAP", model_attributes$coefficient_name)))] <- "Coefficient"

Check warning on line 94 in R/plot.parameters_model.R

View workflow job for this annotation

GitHub Actions / lint-changed-files / lint-changed-files

file=R/plot.parameters_model.R,line=94,col=121,[line_length_linter] Lines should not be more than 120 characters. This line is 133 characters.
}

if (!any(grepl("Parameter", colnames(x), fixed = TRUE))) {
Expand Down Expand Up @@ -140,7 +161,7 @@
if (!is.null(cleaned_parameters)) {
x <- merge(x, cleaned_parameters, sort = FALSE)
x$Parameter <- x$Cleaned_Parameter
if (all(x$Group == "")) {

Check warning on line 164 in R/plot.parameters_model.R

View workflow job for this annotation

GitHub Actions / lint-changed-files / lint-changed-files

file=R/plot.parameters_model.R,line=164,col=15,[nzchar_linter] Use !nzchar(x) instead of x == "". Note that unlike nzchar(), EQ coerces to character, so you'll have to use as.character() if x is a factor. Whenever missing data is possible, please take care to use nzchar(., keepNA = TRUE); nzchar(NA) is TRUE by default.
x$Group <- NULL
} else {
x <- x[!startsWith(x$Group, "SD/Cor"), , drop = FALSE]
Expand All @@ -159,7 +180,7 @@
x <- .fix_facet_names(x)

if (is_bayesian && "Group" %in% colnames(x)) {
x$Effects[x$Group != ""] <- paste0(x$Effects[x$Group != ""], " (", x$Group[x$Group != ""], ")")

Check warning on line 183 in R/plot.parameters_model.R

View workflow job for this annotation

GitHub Actions / lint-changed-files / lint-changed-files

file=R/plot.parameters_model.R,line=183,col=15,[nzchar_linter] Use nzchar(x) instead of x != "". Note that unlike nzchar(), NE coerces to character, so you'll have to use as.character() if x is a factor. Whenever missing data is possible, please take care to use nzchar(., keepNA = TRUE); nzchar(NA) is TRUE by default.

Check warning on line 183 in R/plot.parameters_model.R

View workflow job for this annotation

GitHub Actions / lint-changed-files / lint-changed-files

file=R/plot.parameters_model.R,line=183,col=50,[nzchar_linter] Use nzchar(x) instead of x != "". Note that unlike nzchar(), NE coerces to character, so you'll have to use as.character() if x is a factor. Whenever missing data is possible, please take care to use nzchar(., keepNA = TRUE); nzchar(NA) is TRUE by default.

Check warning on line 183 in R/plot.parameters_model.R

View workflow job for this annotation

GitHub Actions / lint-changed-files / lint-changed-files

file=R/plot.parameters_model.R,line=183,col=80,[nzchar_linter] Use nzchar(x) instead of x != "". Note that unlike nzchar(), NE coerces to character, so you'll have to use as.character() if x is a factor. Whenever missing data is possible, please take care to use nzchar(., keepNA = TRUE); nzchar(NA) is TRUE by default.
}

# remember components
Expand All @@ -175,7 +196,7 @@
is_meta_bma <- !is.null(mc) && any(mc %in% c("meta_random", "meta_fixed", "meta_bma"))

# minor fixes for Bayesian models
if (!is.null(mc) && !is.null(cp) && any(mc %in% c("stanreg", "stanmvreg", "brmsfit")) && length(cp) == length(x$Parameter)) {

Check warning on line 199 in R/plot.parameters_model.R

View workflow job for this annotation

GitHub Actions / lint-changed-files / lint-changed-files

file=R/plot.parameters_model.R,line=199,col=121,[line_length_linter] Lines should not be more than 120 characters. This line is 127 characters.
x$Parameter <- cp
}

Expand All @@ -187,9 +208,9 @@

if (is_bootstrap || isTRUE(is_bayesian)) {
if (is_bootstrap) {
data <- model_attributes$boot_samples

Check warning on line 211 in R/plot.parameters_model.R

View workflow job for this annotation

GitHub Actions / lint-changed-files / lint-changed-files

file=R/plot.parameters_model.R,line=211,col=9,[object_overwrite_linter] 'data' is an exported object from package 'utils'. Avoid re-using such symbols.
} else {
data <- as.data.frame(.retrieve_data(x))

Check warning on line 213 in R/plot.parameters_model.R

View workflow job for this annotation

GitHub Actions / lint-changed-files / lint-changed-files

file=R/plot.parameters_model.R,line=213,col=9,[object_overwrite_linter] 'data' is an exported object from package 'utils'. Avoid re-using such symbols.
}

# MCMC or bootstrapped models
Expand All @@ -197,7 +218,7 @@
insight::format_error("Could not retrieve parameter simulations.")
}

data <- datawizard::reshape_longer(

Check warning on line 221 in R/plot.parameters_model.R

View workflow job for this annotation

GitHub Actions / lint-changed-files / lint-changed-files

file=R/plot.parameters_model.R,line=221,col=7,[object_overwrite_linter] 'data' is an exported object from package 'utils'. Avoid re-using such symbols.
data,
names_to = "Parameter",
rows_to = "Iteration",
Expand Down Expand Up @@ -366,16 +387,26 @@
x$CI <- as.character(x$CI)

x$group <- factor(x$Coefficient < y_intercept, levels = c(FALSE, TRUE))
if (all(x$group == "TRUE")) {
if (all(x$group == "TRUE", na.rm = TRUE)) {
color_scale <- scale_color_material(reverse = TRUE)
} else {
color_scale <- scale_color_material()
}

p <- ggplot2::ggplot(x, ggplot2::aes(
y = .data$Parameter, x = .data$Coefficient,
size = rev(.data$CI), color = .data$group
)) +
# should positive/negative coefficients be highlighted?
if (show_direction) {
p <- ggplot2::ggplot(x, ggplot2::aes(
y = .data$Parameter, x = .data$Coefficient,
size = rev(.data$CI), color = .data$group
))
} else {
p <- ggplot2::ggplot(x, ggplot2::aes(
y = .data$Parameter, x = .data$Coefficient,
size = rev(.data$CI)
))
}

p <- p +
ggplot2::geom_vline(ggplot2::aes(xintercept = y_intercept), linetype = "dotted") +
theme_modern(legend.position = "none") +
color_scale
Expand All @@ -401,16 +432,23 @@
} else {
# plot setup for regular model parameters
x$group <- factor(x$Coefficient < y_intercept, levels = c(FALSE, TRUE))
if (all(x$group == "TRUE")) {
if (all(x$group == "TRUE", na.rm = TRUE)) {
color_scale <- scale_color_material(reverse = TRUE)
} else {
color_scale <- scale_color_material()
}

if (show_direction) {
p <- ggplot2::ggplot(x, ggplot2::aes(y = .data$Parameter, x = .data$Coefficient, color = .data$group)) +
ggplot2::geom_vline(ggplot2::aes(xintercept = y_intercept), linetype = "dotted") +
theme_modern(legend.position = "none") +
color_scale
} else {
p <- ggplot2::ggplot(x, ggplot2::aes(y = .data$Parameter, x = .data$Coefficient)) +
ggplot2::geom_vline(ggplot2::aes(xintercept = y_intercept), linetype = "dotted") +
theme_modern(legend.position = "none") +
color_scale
}

if (show_density) {
p <- p + density_layer
Expand Down
7 changes: 6 additions & 1 deletion R/plot.parameters_simulate.R
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ data_plot.parameters_simulate <- function(x,
out$Component[grepl(paste0(i, "$"), out$Parameter)] <- i
out$Parameter <- gsub(paste0(i, "$"), "", out$Parameter)
}
} else if ("Response" %in% colnames(x)) {
out$Component <- rep(x$Response, each = nrow(out) / nrow(x))
out$Parameter <- rep(x$Parameter, each = nrow(out) / nrow(x))
}

out
Expand Down Expand Up @@ -93,7 +96,9 @@ plot.see_parameters_simulate <- function(x,
ci = 0.95,
...) {
is_mlm <- !is.null(attributes(x)$object_class) && "mlm" %in% attributes(x)$object_class
if (is.null(n_columns) && isTRUE(is_mlm)) n_columns <- 1
if (is.null(n_columns) && (isTRUE(is_mlm) || "Response" %in% colnames(x))) {
n_columns <- 1
}

# check for defaults
if (missing(centrality) && !is.null(attributes(x)$centrality)) {
Expand Down
14 changes: 14 additions & 0 deletions man/plot.see_parameters_model.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 20 additions & 1 deletion tests/testthat/test-plot.parameters_model.R
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ test_that("`plot.see_parameters_model()` works", {
title = "plot.model_parameters_1",
fig = plot(result)
)
vdiffr::expect_doppelganger(
title = "plot.model_parameters_no_dir",
fig = plot(result, show_direction = FALSE)
)
})

test_that("`plot.see_parameters_model()` random parameters works", {
Expand Down Expand Up @@ -69,7 +73,7 @@ test_that("`plot.see_parameters_model()` random parameters works", {
data(sleepstudy, package = "lme4")

set.seed(12345)
sleepstudy$grp <- sample(1:5, size = 180, replace = TRUE)
sleepstudy$grp <- sample.int(5, size = 180, replace = TRUE)
model <- lme4::lmer(
Reaction ~ Days + (1 | grp) + (1 | Subject),
data = sleepstudy
Expand All @@ -80,3 +84,18 @@ test_that("`plot.see_parameters_model()` random parameters works", {
fig = plot(out)
)
})


test_that("`plot.see_parameters_model()` random parameters works", {
skip_if_not_installed("vdiffr")
skip_if_not_installed("mgcv")
skip_if_not_installed("parameters")

data(mtcars)
m <- mgcv::gam(mpg ~ s(wt) + cyl + gear + disp, data = mtcars)
result <- parameters::model_parameters(m)
vdiffr::expect_doppelganger(
title = "plot.model_parameters_gam",
fig = plot(result)
)
})
42 changes: 42 additions & 0 deletions tests/testthat/test-plot.simulate_parameters.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
skip_if(TRUE)

## FIXME: currently does not retrieve the data

skip_on_cran()
skip_if_offline()
skip_if_not_installed("mclogit")
skip_if_not_installed("parameters")
skip_if_not_installed("vdiffr")

test_that("`plot()` for simulate_parameters", {
pict <- base::readRDS(url("https://slcladal.github.io/data/pict.rda", "rb"))
suppressWarnings({
m1.mn <- mclogit::mblogit(
formula = Response ~ Gender + Group,
random = ~ 1 | Item,
data = pict
)
})
set.seed(1234)
ms <- parameters::simulate_parameters(m1.mn)
set.seed(1234)
vdiffr::expect_doppelganger(
title = "plot.simulate_parameters works",
fig = plot(ms)
)
set.seed(1234)
vdiffr::expect_doppelganger(
title = "plot.simulate_parameters works-2",
fig = plot(ms, stack = FALSE)
)
set.seed(1234)
vdiffr::expect_doppelganger(
title = "plot.simulate_parameters works-3",
fig = plot(ms, stack = FALSE, show_intercept = TRUE, normalize_height = TRUE)
)
set.seed(1234)
vdiffr::expect_doppelganger(
title = "plot.simulate_parameters works-4",
fig = plot(ms, stack = TRUE, show_intercept = TRUE, normalize_height = TRUE)
)
})
Loading