| 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--------------