Title: | Easy Visualization of Conditional Effects from Regression Models |
Version: | 1.1.0 |
Description: | Offers a flexible and user-friendly interface for visualizing conditional effects from a broad range of regression models, including mixed-effects and generalized additive (mixed) models. Compatible model types include lm(), rlm(), glm(), glm.nb(), and gam() (from 'mgcv'); nonlinear models via nls(); and generalized least squares via gls(). Mixed-effects models with random intercepts and/or slopes can be fitted using lmer(), glmer(), glmer.nb(), glmmTMB(), or gam() (from 'mgcv', via smooth terms). Plots are rendered using base R graphics with extensive customization options. Approximate confidence intervals for nls() models are computed using the delta method. Robust standard errors for rlm() are computed using the sandwich estimator (Zeileis 2004) <doi:10.18637/jss.v011.i10>. Methods for generalized additive models follow Wood (2017) <doi:10.1201/9781315370279>. For linear mixed-effects models with 'lme4', see Bates et al. (2015) <doi:10.18637/jss.v067.i01>. For mixed models using 'glmmTMB', see Brooks et al. (2017) <doi:10.32614/RJ-2017-066>. |
Maintainer: | Luca Corlatti <lucac1980@yahoo.it> |
Imports: | stats, utils, graphics, grDevices |
Suggests: | nlme, lme4, MASS, glmmTMB, mgcv, numDeriv, sandwich |
License: | GPL-3 |
Encoding: | UTF-8 |
RoxygenNote: | 7.3.2 |
NeedsCompilation: | no |
Packaged: | 2025-08-21 19:19:35 UTC; lucacorlatti |
Author: | Luca Corlatti [aut, cre] |
Repository: | CRAN |
Date/Publication: | 2025-08-21 19:42:05 UTC |
Easy Visualization of Conditional Effects from Regression Models
Description
easyViz
offers a flexible and user-friendly interface for visualizing conditional effects
from a broad range of regression and mixed-effects models using base R graphics.
Usage
easyViz(
model,
data,
predictor,
by = NULL,
pred_type = "response",
pred_range_limit = TRUE,
pred_on_top = FALSE,
pred_resolution = 101,
num_conditioning = "median",
cat_conditioning = "mode",
fix_values = NULL,
re.form = NULL,
backtransform_response = NULL,
xlim = NULL,
ylim = NULL,
xlab = NULL,
ylab = NULL,
cat_labels = NULL,
font_family = "",
las = 1,
bty = "o",
plot_args = list(),
show_data_points = TRUE,
binary_data_type = "plain",
bins = 10,
jitter_data_points = FALSE,
point_col = rgb(0, 0, 0, alpha = 0.4),
point_pch = 16,
point_cex = 0.75,
pred_line_col = "black",
pred_line_lty = c(1, 2, 3, 4),
pred_line_lwd = 2,
ci_type = "polygon",
ci_polygon_col = c("gray", "black", "lightgray", "darkgray"),
ci_line_col = "black",
ci_line_lty = c(1, 2, 3, 4),
ci_line_lwd = 1,
pred_point_col = c("black", "gray", "darkgray", "lightgray"),
pred_point_pch = 16,
pred_point_cex = 1,
ci_bar_col = "black",
ci_bar_lty = 1,
ci_bar_lwd = 1,
ci_bar_caps = 0.1,
add_legend = FALSE,
legend_position = "top",
legend_title = NULL,
legend_labels = NULL,
legend_title_size = 1,
legend_label_size = 0.9,
legend_horiz = FALSE,
legend_args = list()
)
Arguments
model |
[required] A fitted model object (e.g., |
data |
[required] The data frame used to fit the model (e.g., |
predictor |
[required] The name of the target explanatory variable to be plotted (e.g., |
by |
The name of an interaction or additional variable for conditioning (e.g.,
Although |
pred_type |
Character string indicating the type of predictions to plot.
Either |
pred_range_limit |
Logical. Applies only when the predictor is numeric and a categorical |
pred_on_top |
Logical. If |
pred_resolution |
Number of prediction points to use for numeric predictors.
Defaults to |
num_conditioning |
How to condition non-target numeric predictors. Either |
cat_conditioning |
How to condition non-target categorical predictors.
Either |
fix_values |
A named vector or named list specifying fixed values for one or more variables during prediction.
Supports both numeric and categorical variables.
For numeric variables, specify a fixed value (e.g., |
re.form |
A formula specifying which random effects to include when generating predictions.
This argument is relevant for mixed-effects models only (e.g., from
For |
backtransform_response |
A custom function to back-transform predictions for transformed response variables
(e.g., |
xlim |
x-axis limits for the plot (e.g., |
ylim |
y-axis limits for the plot (e.g., |
xlab |
x-axis labels (e.g., |
ylab |
y-axis labels (e.g., |
cat_labels |
Custom labels for levels of a categorical predictor (e.g., |
font_family |
Font family for the plot. E.g., |
las |
Text orientation for axis labels (default: |
bty |
Box type around the plot. E.g., |
plot_args |
A named list of additional graphical parameters passed to base R's
For a full list of supported parameters, see |
show_data_points |
Logical. Whether to display raw data points (default: |
binary_data_type |
For binary responses, how to display raw data points in the plot.
Either |
bins |
Number of bins for displaying binary response raw data when |
jitter_data_points |
Logical. If |
point_col |
Point color for raw data (default: |
point_pch |
Point shape for raw data (default: |
point_cex |
Point size for raw data (default: |
pred_line_col |
Color of the predicted line for numerical predictors (default: |
pred_line_lty |
Type of the predicted line for numerical predictors (default: |
pred_line_lwd |
Width of the predicted line for numerical predictors (default: |
ci_type |
Type of 95 percent confidence intervals for numeric predictors.
Either |
ci_polygon_col |
Color for 95 percent confidence interval polygon (default: |
ci_line_col |
Color for 95 percent confidence interval lines (default: |
ci_line_lty |
Type for 95 percent confidence interval lines (default: |
ci_line_lwd |
Width for 95 percent confidence interval lines (default: |
pred_point_col |
Color for predicted point values of categorical predictors (default: |
pred_point_pch |
Shape for predicted point values of categorical predictors (default: |
pred_point_cex |
Size for predicted point values of categorical predictors (default: |
ci_bar_col |
Color for 95 percent confidence interval bars (default: |
ci_bar_lty |
Type for 95 percent confidence interval bars (default: |
ci_bar_lwd |
Width for 95 percent confidence interval bars (default: |
ci_bar_caps |
Size of the caps on 95 percent confidence interval bars (default: |
add_legend |
Logical. Whether to add a legend for |
legend_position |
Legend position. Either a named position string ( |
legend_title |
Optional character string. If specified, this will appear as the title of the legend.
In this case, the legend labels will correspond to the levels of the |
legend_labels |
Custom labels for the legend (e.g., |
legend_title_size |
Numeric. Text size for the legend title (default: |
legend_label_size |
Numeric. Text size for the legend labels (default: |
legend_horiz |
Logical. If |
legend_args |
A named list of additional arguments passed to base R's
For a full list of supported parameters, see |
Details
This function provides an easy-to-use yet highly flexible tool for visualizing conditional effects
from a wide range of regression models, including mixed-effects and generalized additive (mixed) models.
Compatible model types include lm
, rlm
, glm
, glm.nb
, and mgcv::gam
;
nonlinear models via nls
; and generalized least squares via gls
.
Mixed-effects models with random intercepts and/or slopes can be fitted using lmer
, glmer
, glmer.nb
,
glmmTMB
, or mgcv::gam
(via smooth terms).
The function handles nonlinear relationships (e.g., splines, polynomials), two-way interactions,
and supports visualization of three-way interactions via conditional plots.
Plots are rendered using base R graphics with extensive customization options available through the plot_args
and
legend_args
argument. Users can pass any valid graphical parameters accepted by plot
, par
or legend
enabling full control over axis/legend labels, font styles, colors, margins, and more.
Tip: To customize plot appearance, look for argument names by prefix:
Arguments starting with point_
control the appearance of raw data.
Arguments starting with pred_
control the appearance of predicted values (lines or points).
Arguments beginning with ci_
adjust the display of confidence intervals (polygons, lines or bars).
Arguments beginning with legend_
control the appearance of the legend.
This naming convention simplifies styling: just type the prefix (point
, pred
, ci
, or legend
)
to discover relevant arguments.
The arguments model
, data
, and predictor
are required.
The function will return an error if any of them is missing or invalid.
Value
A base R plot visualizing the conditional effect of a predictor on the response variable.
Additionally, a data frame is invisibly returned containing the predictor values, conditioning variables,
predicted values (fit
), and their 95 percent confidence intervals (lower
, upper
).
To extract prediction data for further use (e.g., custom plotting or tabulation), assign the output to an object:
pred_df <- easyViz(...)
. You can then inspect it using head(pred_df)
or save it with write.csv(pred_df, ...)
.
Examples
#------------------------------------------
# Load required packages
#------------------------------------------
library(nlme)
library(MASS)
library(lme4)
library(glmmTMB)
library(mgcv)
#------------------------------------------
# Simulate dataset
#------------------------------------------
set.seed(123)
n <- 100
x1 <- rnorm(n)
x2 <- rnorm(n)
x3 <- runif(n, 0, 5)
x4 <- factor(sample(letters[1:3], n, replace = TRUE))
group_levels <- paste0("G", 1:10)
group <- factor(sample(group_levels, n, replace = TRUE))
# Generate random intercepts for each group
group_effects <- rnorm(length(group_levels), mean = 0, sd = 2) # non-zero variance
names(group_effects) <- group_levels
group_intercept <- group_effects[as.character(group)]
# Non-linear continuous response
true_y <- 5 * sin(x3) + 3 * x1 + group_intercept + model.matrix(~x4)[, -1] %*% c(2, -2)
noise <- rnorm(n, sd = 3)
y <- as.vector(true_y + noise)
# Binary response with group effect added to logit
logit_p <- 2 * x1 - 1 + group_intercept
p <- 1 / (1 + exp(-logit_p))
binary_y <- rbinom(n, size = 1, prob = p)
# Binomial response: number of successes and failures
y3 <- sample(10:30, n, replace = TRUE)
logit_p_prop <- -1.5 * scale(x1)
p_prop <- 1 / (1 + exp(-logit_p_prop))
y1 <- rbinom(n, size = y3, prob = p_prop) # successes
y2 <- y3 - y1 # failures
# Count response with group effect in log(mu)
mu_count <- exp(1 + 0.8 * x2 - 0.5 * (x4 == "b") + group_intercept)
size <- 1.2
count_y <- rnbinom(n, size = size, mu = mu_count)
# Offset variable
offset_var <- log(runif(n, 1, 10))
# Assemble dataset
sim_data <- data.frame(x1, x2, x3, x4, group, y, binary_y, y1, y2, y3, count_y, offset_var)
#------------------------------------------
# 1. Linear model (lm)
#------------------------------------------
mod_lm <- lm(y ~ x1 + x4,
data = sim_data)
easyViz(model = mod_lm, data = sim_data, predictor = "x1",
by = "x4",
pred_range_limit = FALSE,
pred_on_top = TRUE,
bty = "n",
ylim = c(-12,18),
xlab = "Predictor x1",
ylab = "Response y",
point_col = ifelse(sim_data$x4=="a", "red",
ifelse(sim_data$x4=="b", "orange",
"yellow")),
point_cex = 0.5,
pred_line_col = c("red", "orange", "yellow"),
pred_line_lty = 1,
ci_polygon_col = c(rgb(1,0,0,0.5),
rgb(1,0.5,0,0.5),
rgb(1,1,0,0.5)),
add_legend = TRUE,
legend_position = "top",
legend_title = "Predictor x4",
legend_labels = c("a", "b", "c"),
legend_horiz = TRUE,
legend_args = list(pch = 16))
mod_lm2 <- lm(sqrt(x3) ~ x1 * x4,
data = sim_data)
easyViz(model = mod_lm2, data = sim_data, predictor = "x1",
by="x4",
backtransform_response = function(x) x^2,
ylim = c(0,8),
show_data_points = FALSE,
add_legend = TRUE)
mod_lm3 <- lm(y ~ poly(x3, 3),
data = sim_data)
easyViz(model = mod_lm3, data = sim_data, predictor = "x3",
pred_on_top = TRUE,
font_family = "mono",
point_col = rgb(1,0,0,0.3),
point_pch = "+",
ci_type = "lines",
ci_line_lty = 2)
# Extract prediction data
pred_df <- easyViz(model = mod_lm, data = sim_data, predictor = "x1", by = "x4")
head(pred_df)
#------------------------------------------
# 2. Robust linear model (rlm)
#------------------------------------------
mod_rlm <- rlm(y ~ x1 + x4,
data = sim_data)
easyViz(model = mod_rlm, data = sim_data, predictor = "x1",
by = "x4",
pred_on_top = TRUE,
bty = "n",
xlim = c(-2.2,3.5), # extend x-axis limits
xlab = "", # temporarily remove x-axis label
ylab = "Response y",
plot_args = list(xaxp=c(-2, 2, 4)), # set tick marks
point_col = ifelse(sim_data$x4=="a", "red",
ifelse(sim_data$x4=="b", "orange",
"yellow")),
point_cex = 0.5,
pred_line_col = c("red", "orange", "yellow"),
pred_line_lty = 1,
ci_polygon_col = c(rgb(1,0,0,0.5),
rgb(1,0.5,0,0.5),
rgb(1,1,0,0.5)),
add_legend = TRUE,
legend_position = c(2.25,13),
legend_title = "Predictor x4",
legend_title_size = 0.9,
legend_labels = c("a", "b", "c"),
legend_horiz = FALSE,
legend_args = list(pch = 16))
# Then manually add centered x-axis label
text(x = 0, y = -18.2, labels = "Predictor x1", xpd = NA)
#------------------------------------------
# 3. Generalized least squares (gls)
#------------------------------------------
mod_gls <- gls(y ~ x1 + x2 + x4,
correlation = corAR1(form = ~1|group),
data = sim_data)
easyViz(model = mod_gls, data = sim_data, predictor = "x4",
jitter_data_points = TRUE,
bty = "n",
xlab = "Predictor x4",
ylab = "Response y",
point_col = rgb(0,0,1,0.2),
pred_point_col = "blue",
cat_labels = c("group A", "group B", "group C"))
sim_data$x5 <- sample(c(rep("CatA", 50), rep("CatB", 50)))
mod_gls2 <- gls(y ~ x1 + x2 + x4 * x5,
correlation = corAR1(form = ~1|group),
data = sim_data)
easyViz(model = mod_gls2, data = sim_data, predictor = "x4",
by = "x5",
jitter_data_points = TRUE,
bty = "n",
ylim = c(-15,15),
xlim=c(0.75,4), # extend x-axis limits
xlab = "", # temporarily remove x-axis label
ylab = "Response y",
cat_labels = c("group A", "group B", "group C"),
point_col = c(rgb(0,0,1,0.2), rgb(1,0,0,0.2)),
pred_point_col = c("blue", "red"),
ci_bar_caps = 0,
add_legend = TRUE,
legend_position = "topright",
legend_args = list(title = "Predictor x5",
title.cex = 1,
legend = c("A", "B"),
pt.cex = 1.5,
horiz = TRUE))
# Then manually add centered x-axis label
text(x = 2, y = -23.2, labels = "Predictor x4", xpd = NA)
#------------------------------------------
# 4. Nonlinear least squares (nls)
#------------------------------------------
mod_nls <- nls(y ~ a * sin(b * x3) + c,
data = sim_data,
start = list(a = 5, b = 1, c = 0))
summary(mod_nls)
easyViz(model = mod_nls, data = sim_data, predictor = "x3",
pred_on_top = TRUE,
font_family = "serif",
bty = "n",
xlab = "Predictor x3",
ylab = "Response y",
point_col = rgb(0,1,0,0.7),
point_pch = 1,
ci_type = "lines",
ci_line_col = "black",
ci_line_lty = 2)
text(x = 2.5, y = 11,
labels = expression(Y %~% 5.31584 %*% sin(1.08158 %*% X[3]) + 0.51338),
cex = 0.7)
#------------------------------------------
# 5. Generalized linear model (glm)
#------------------------------------------
mod_glm <- glm(binary_y ~ x1 + x4 + offset(log(offset_var)),
family = binomial(link="cloglog"),
data = sim_data)
easyViz(model = mod_glm, data = sim_data, predictor = "x1",
fix_values = list(x4="b", offset_var=1),
xlab = "Predictor x1",
ylab = "Response y",
binary_data_type = "binned",
point_col = "black",
ci_polygon_col = "red")
easyViz(model = mod_glm, data = sim_data, predictor = "x4",
bty = "n",
xlab = "Predictor x4",
ylab = "Response y",
binary_data_type = "plain",
jitter_data_points = TRUE,
point_col = "black",
point_pch = "|",
point_cex = 0.5)
mod_glm2 <- glm(y1/y3 ~ x1 + x4, weights = y3,
family = binomial(link="logit"),
data = sim_data)
easyViz(model = mod_glm2, data = sim_data, predictor = "x1",
pred_on_top = TRUE,
xlab = "Predictor x1",
ylab = "Response y",
point_col = "black",
ci_polygon_col = "red")
#------------------------------------------
# 6. Negative binomial GLM (glm.nb)
#------------------------------------------
mod_glm_nb <- glm.nb(count_y ~ x2,
data = sim_data)
easyViz(model = mod_glm_nb, data = sim_data, predictor = "x2",
font_family = "mono",
bty = "L",
plot_args = list(main = "NB model"),
xlab = "Predictor x2",
ylab = "Response y",
ci_polygon_col = "blue")
#------------------------------------------
# 7. Linear mixed-effects model (lmer)
#------------------------------------------
mod_lmer <- lmer(y ~ x1 + x4 + (1 | group),
data = sim_data)
easyViz(model = mod_lmer, data = sim_data, predictor = "x1",
by="group",
re.form = NULL,
bty = "n",
plot_args = list(xaxp = c(round(min(sim_data$x1),1),
round(max(sim_data$x1),1), 5)),
ylim = c(-15, 15),
xlab = "Predictor x1",
ylab = "Response y",
pred_line_col = "green",
pred_line_lty = 1,
pred_line_lwd = 1)
oldpar <- par(new = TRUE)
easyViz(model = mod_lmer, data = sim_data, predictor = "x1",
re.form = NA,
bty = "n",
plot_args = list(xaxp = c(round(min(sim_data$x1),1),
round(max(sim_data$x1),1), 5)),
show_data_points = FALSE,
xlab = "Predictor x1",
ylab = "Response y",
ylim = c(-15, 15),
pred_line_col = "red",
pred_line_lty = 1,
pred_line_lwd = 2,
ci_type = NULL)
par(oldpar)
#------------------------------------------
# 8. Generalized linear mixed model (glmer)
#------------------------------------------
mod_glmer <- glmer(binary_y ~ x1 + x4 + (1 | group),
family = binomial,
data = sim_data)
easyViz(model = mod_glmer, data = sim_data, predictor = "x1",
by = "group",
re.form = NULL,
cat_conditioning = "reference",
font_family = "serif",
xlab = "Predictor x1",
ylab = "Response y",
binary_data_type = "binned",
pred_range_limit = FALSE,
pred_line_col = "blue",
pred_line_lty = 1,
pred_line_lwd = 1)
#------------------------------------------
# 9. GLMM with negative binomial (glmer.nb)
#------------------------------------------
mod_glmer_nb <- glmer.nb(count_y ~ x2 + x4 + (1 | group),
data = sim_data)
easyViz(model = mod_glmer_nb, data = sim_data, predictor = "x2",
re.form = NA,
bty = "n",
xlab = "Predictor x2",
ylab = "Response y",
ylim = c(0, 120),
point_pch = 1)
#------------------------------------------
# 10. GLMM using glmmTMB
#------------------------------------------
mod_glmmTMB <- glmmTMB(count_y ~ x2 + x4 + (1 | group),
ziformula = ~ x2,
family = nbinom2,
data = sim_data)
easyViz(model = mod_glmmTMB, data = sim_data, predictor = "x2",
re.form = NA,
bty = "n",
xlab = "Predictor x2",
ylab = "Response y",
ylim = c(0, 120),
point_pch = 1,
ci_type = NULL)
#------------------------------------------
# 11. GAM with random smooth for group
#------------------------------------------
mod_gam <- gam(y ~ s(x3) + s(group, bs = "re"),
data = sim_data)
easyViz(model = mod_gam, data = sim_data, predictor = "x3",
re.form = NA,
las = 0,
bty = "n",
xlab = "Predictor x3",
ylab = "Response y",
point_col = "black",
point_pch = 1,
ci_polygon_col = rgb(1,0,0,0.5))
#------------------------------------------
# 12. Plotting 3-way interaction
#------------------------------------------
mod_lm_int <- lm(y ~ x1*x2*x3,
data = sim_data)
# Check conditional values to use for plotting
quantile(x2, c(0.1,0.5, 0.9))
quantile(x3, c(0.1,0.5, 0.9))
# (optional) Generate a customizable function to add a strip label at the top
add_strip_label <- function(label, bg = "grey90", cex = 1, font = 2, height_mult = 2.5) {
usr <- par("usr")
x_left <- usr[1]
x_right <- usr[2]
y_top <- usr[4]
# Estimate strip height using text height
h <- strheight(label, cex = cex) * height_mult
# Strip coordinates (extending above the plotting region)
y_bottom <- y_top + 0.2 * h
y_top_box <- y_bottom + h
# Draw the full-width strip
rect(x_left, y_bottom, x_right, y_top_box, col = bg, border = "black", xpd = NA)
# Add centered text
text(x = mean(c(x_left, x_right)),
y = mean(c(y_bottom, y_top_box)),
labels = label, cex = cex, font = font, xpd = NA)
}
# par settings for multi-panel plot
old_mfrow <- par(mfrow = c(1, 3))
old_oma <- par(oma = c(4, 4, 2, 1))
old_mar <- par(mar = c(0, 0, 2, 0))
# Panel 1
easyViz(model = mod_lm_int, data = sim_data, predictor = "x1",
by = "x2",
fix_values = c(x3 = 0.5750978),
plot_args = list(xlab = "", ylab = ""),
show_data_points = FALSE,
pred_line_col = c(2, 3, 4),
ci_polygon_col = c(2, 3, 4),
add_legend = TRUE,
legend_position = "topleft",
legend_labels = c("x2 = -1.3", "x2 = -0.2", "x2 = 1.5"))
add_strip_label("x3 = 0.6")
mtext("Response y", side = 2, outer = TRUE, line = 2.5)
# Panel 2
easyViz(model = mod_lm_int, data = sim_data, predictor = "x1",
by = "x2",
fix_values = c(x3 = 2.3095046),
plot_args = list(yaxt = "n", xlab = "", ylab = ""),
show_data_points = FALSE,
pred_line_col = c(2, 3, 4),
ci_polygon_col = c(2, 3, 4))
add_strip_label("x3 = 2.3")
# Panel 3
easyViz(model = mod_lm_int, data = sim_data, predictor = "x1",
by = "x2",
fix_values = c(x3 = 4.4509078),
plot_args = list(yaxt = "n", xlab = "", ylab = ""),
show_data_points = FALSE,
pred_line_col = c(2, 3, 4),
ci_polygon_col = c(2, 3, 4))
add_strip_label("x3 = 4.5")
mtext("Predictor x1", side = 1, outer = TRUE, line = 2.5)
# Restore original settings
par(old_mfrow)
par(old_oma)
par(old_mar)
#-------------END OF EXAMPLES--------------