Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
4ea0ae0
Fix mapping_string to handle multi-line expressions
schloerke Feb 2, 2026
e9b2e62
Move tests to longer file
schloerke Feb 2, 2026
58f21ee
Update ggparcoord test for new ggplot2 version
schloerke Feb 2, 2026
41716a0
Update ggmatrix_add.md
schloerke Feb 2, 2026
5fad4cf
Update density diag snaps
schloerke Feb 2, 2026
cdf524e
Create zzzz_ggmatrix.md
schloerke Feb 2, 2026
aa680ed
Remove "Smoker ?" warning being printed
schloerke Feb 2, 2026
0f940d0
Wrap broomify example in require(broom) check
schloerke Feb 2, 2026
f9f8101
Skip vdiffr tests during depends-only checks
schloerke Feb 2, 2026
b1181b4
Add skip_if_not_installed checks to test files
schloerke Feb 2, 2026
2025482
Update broomify.Rd
schloerke Feb 2, 2026
a2e34d9
Remove tryCatch from ggmatrix test block
schloerke Feb 2, 2026
e242f2a
Ignore Claude-related files in build and git
schloerke Feb 2, 2026
5a18093
Standardize snapshot names in doppelganger helper
schloerke Feb 2, 2026
131addc
Update ignore files and remove outline document
schloerke Feb 2, 2026
fff2a2f
Remove unused lifecycle SVG badge images
schloerke Feb 2, 2026
ea72d5f
Wrap example code in require(broom) checks
schloerke Feb 2, 2026
7370def
Add skip_if_not_installed checks to tests
schloerke Feb 2, 2026
eeb9d48
Update lifecycle badge for ggmatrix_location
schloerke Feb 2, 2026
ccade41
Use map_data for ggplot2 >= 4.0.0 in fix_data
schloerke Feb 2, 2026
37d1615
Update Rd links to reference ggstats functions
schloerke Feb 3, 2026
4f9d704
Update map data handling for ggplot2 v4 compatibility
schloerke Feb 3, 2026
7d78462
`devtools::document()` (GitHub Actions)
schloerke Feb 3, 2026
99f0769
Add script to remove _snaps from .Rbuildignore
schloerke Feb 3, 2026
8f4f274
Wrap autopoint examples with ggforce check
schloerke Feb 3, 2026
3c44444
Hash ggmatrix test names for long file name NOTE; update snaps
schloerke Feb 3, 2026
6121758
Adjust examples to work with no deps
schloerke Feb 3, 2026
d9cda40
Skip vdiffr on non-macOS; update snaps handling
schloerke Feb 3, 2026
366ff61
Skip vdiffr tests on R != 4.5
schloerke Feb 4, 2026
7d0533e
Fix R4.3 failure
schloerke Feb 4, 2026
ca8c445
Guard density examples with require(MASS)
schloerke Feb 4, 2026
3ca3770
protect density example that possibly uses MASS pkg
schloerke Feb 4, 2026
f1b35b4
Update ggpairs.Rd
schloerke Feb 4, 2026
fb1f421
More docs safety
schloerke Feb 4, 2026
8296383
Update NEWS.md
schloerke Feb 4, 2026
d8623b6
Fix duplicate aesthetics warning in ggsurv() for upcoming ggplot2 (#572)
Copilot Feb 4, 2026
fe8b3da
Disable vdiffr snapshot testing on GHA. booooooooo
schloerke Feb 4, 2026
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
4 changes: 3 additions & 1 deletion .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ figure
ggmapTemp.png
README.html
notes/
tests/testthat/_snaps
tests/testthat/_snaps/*/*.svg
tests/testthat/Rplots.pdf
^.*\.Rproj$
^\.Rproj\.user$
Expand All @@ -37,3 +37,5 @@ ggduo_paper.txt
^CRAN-SUBMISSION$
.vscode
^data-raw$
^\.claude$
^_dev$
34 changes: 34 additions & 0 deletions .github/shiny-workflows/check.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/usr/bin/env Rscript

# This script works in tandem with
# rstudio/shiny-workflows/.github/workflows/R-CMD-check.yaml@v1 GHA job

# Remove tests/testthat/_snaps from .Rbuildignore
# This ensures snapshot tests are included in R CMD check but not in the package build for a CRAN submission

# If not on macOS, skip vdiffr tests
# This logic is tied to `ggally_expect_doppelganger()` in
# tests/testthat/helper-doppelganger.R
if ((!identical(tolower(Sys.info()[["sysname"]]), "darwin"))) {
quit(status = 0)
}

rbuildignore_path <- ".Rbuildignore"

if (!file.exists(rbuildignore_path)) {
stop(".Rbuildignore file not found")
}

# Read the file
lines <- readLines(rbuildignore_path)

# Remove the line containing "tests/testthat/_snaps/"
lines_filtered <- lines[!grepl("^tests/testthat/_snaps/", lines)]

# Write back only if changes were made
if (length(lines) != length(lines_filtered)) {
writeLines(lines_filtered, rbuildignore_path)
message("Removed 'tests/testthat/_snaps/' from .Rbuildignore")
} else {
message("'tests/testthat/_snaps/' not found in .Rbuildignore")
}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ inst/doc
doc
Meta
CRAN-RELEASE
.claude/*.local.*
_dev/
1 change: 1 addition & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ Suggests:
labelled,
mapproj,
maps (>= 3.1.0),
MASS,
network (>= 1.17.1),
nnet,
rmarkdown,
Expand Down
14 changes: 14 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# GGally (development version)

* Fixed duplicate aesthetics warning in `ggsurv()` with upcoming ggplot2 version. Removed duplicate `lty` aesthetic mapping from confidence interval bounds. (#572)

* Fixed `mapping_string()` to properly handle long aesthetic expressions by collapsing multi-line `deparse()` output. (#573)

* Updated `fix_data()` to handle map objects correctly with ggplot2 >= 4.0.0 using `ggplot2::map_data()` instead of `fortify()`. (#573)

* Wrapped documentation examples requiring optional packages (`{MASS}`, `{broom}`, `{network}`, `{sna}`, `{ggforce}`) in `if (require(...))` blocks to prevent errors when packages are not installed. (#573)

* Added `{MASS}` to Suggests in DESCRIPTION to support density plot examples. (#573)

* Updated `.Rbuildignore` to exclude `{vdiffr}` snapshot SVG files more specifically. (#573)

* Added GitHub Actions check script to conditionally remove snapshot paths from `.Rbuildignore` for macOS testing. (#573)

# GGally 2.4.0

* Replace internal usage with the base pipe (`|>`). (Thank you @m-muecke! #554)
Expand Down
50 changes: 27 additions & 23 deletions R/gg-plots.R
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ eval_data_col <- function(data, aes_col) {
#' mapping <- ggplot2::aes(Petal.Length)
#' mapping_string(mapping$x)
mapping_string <- function(aes_col) {
gsub("^~(?:\\.data\\$)?", "", deparse(aes_col, 500L))
gsub("^~(?:\\.data\\$)?", "", paste0(deparse(aes_col, 500L), collapse = ""))
}

# is categories on the left?
Expand Down Expand Up @@ -208,15 +208,17 @@ ggally_smooth_lm <- function(data, mapping, ...) {
#' p_ <- GGally::print_if_interactive
#'
#' data(tips)
#' p_(ggally_density(tips, mapping = ggplot2::aes(x = total_bill, y = tip)))
#' p_(ggally_density(
#' tips,
#' mapping = ggplot2::aes(total_bill, tip, fill = after_stat(level))
#' ))
#' p_(ggally_density(
#' tips,
#' mapping = ggplot2::aes(total_bill, tip, fill = after_stat(level))
#' ) + ggplot2::scale_fill_gradient(breaks = c(0.05, 0.1, 0.15, 0.2)))
#' if (require(MASS)) {
#' p_(ggally_density(tips, mapping = ggplot2::aes(x = total_bill, y = tip)))
#' p_(ggally_density(
#' tips,
#' mapping = ggplot2::aes(total_bill, tip, fill = after_stat(level))
#' ))
#' p_(ggally_density(
#' tips,
#' mapping = ggplot2::aes(total_bill, tip, fill = after_stat(level))
#' ) + ggplot2::scale_fill_gradient(breaks = c(0.05, 0.1, 0.15, 0.2)))
#' }
ggally_density <- function(data, mapping, ...) {
rangeX <- range(eval_data_col(data, mapping$x), na.rm = TRUE)
rangeY <- range(eval_data_col(data, mapping$y), na.rm = TRUE)
Expand Down Expand Up @@ -1751,19 +1753,21 @@ ggally_naDiag <- function(...) {
#' p_ <- GGally::print_if_interactive
#'
#' data(tips)
#' p_(ggally_autopoint(tips, mapping = aes(x = tip, y = total_bill)))
#' p_(ggally_autopoint(tips, mapping = aes(x = tip, y = sex)))
#' p_(ggally_autopoint(tips, mapping = aes(x = smoker, y = sex)))
#' p_(ggally_autopoint(tips, mapping = aes(x = smoker, y = sex, color = day)))
#' p_(ggally_autopoint(tips, mapping = aes(x = smoker, y = sex), size = 8))
#' p_(ggally_autopoint(tips, mapping = aes(x = smoker, y = sex), alpha = .9))
#'
#' p_(ggpairs(
#' tips,
#' mapping = aes(colour = sex),
#' upper = list(discrete = "autopoint", combo = "autopoint", continuous = "autopoint"),
#' diag = list(discrete = "autopointDiag", continuous = "autopointDiag")
#' ))
#' if (require(ggforce)) {
#' p_(ggally_autopoint(tips, mapping = aes(x = tip, y = total_bill)))
#' p_(ggally_autopoint(tips, mapping = aes(x = tip, y = sex)))
#' p_(ggally_autopoint(tips, mapping = aes(x = smoker, y = sex)))
#' p_(ggally_autopoint(tips, mapping = aes(x = smoker, y = sex, color = day)))
#' p_(ggally_autopoint(tips, mapping = aes(x = smoker, y = sex), size = 8))
#' p_(ggally_autopoint(tips, mapping = aes(x = smoker, y = sex), alpha = .9))
#'
#' p_(ggpairs(
#' tips,
#' mapping = aes(colour = sex),
#' upper = list(discrete = "autopoint", combo = "autopoint", continuous = "autopoint"),
#' diag = list(discrete = "autopointDiag", continuous = "autopointDiag")
#' ))
#' }
ggally_autopoint <- function(data, mapping, ...) {
rlang::check_installed("ggforce")

Expand Down
25 changes: 13 additions & 12 deletions R/ggcoef.R
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,19 @@
#' # Small function to display plots only if it's interactive
#' p_ <- GGally::print_if_interactive
#'
#' library(broom)
#' reg <- lm(Sepal.Length ~ Sepal.Width + Petal.Length + Petal.Width, data = iris)
#' p_(ggcoef(reg))
#' \donttest{
#' d <- as.data.frame(Titanic)
#' reg2 <- glm(Survived ~ Sex + Age + Class, family = binomial, data = d, weights = d$Freq)
#' ggcoef(reg2, exponentiate = TRUE)
#' ggcoef(
#' reg2,
#' exponentiate = TRUE, exclude_intercept = TRUE,
#' errorbar_height = .2, color = "blue", sort = "ascending"
#' )
#' if (require(broom)) {
#' reg <- lm(Sepal.Length ~ Sepal.Width + Petal.Length + Petal.Width, data = iris)
#' p_(ggcoef(reg))
#' \donttest{
#' d <- as.data.frame(Titanic)
#' reg2 <- glm(Survived ~ Sex + Age + Class, family = binomial, data = d, weights = d$Freq)
#' ggcoef(reg2, exponentiate = TRUE)
#' ggcoef(
#' reg2,
#' exponentiate = TRUE, exclude_intercept = TRUE,
#' errorbar_height = .2, color = "blue", sort = "ascending"
#' )
#' }
#' }
#' @export
ggcoef <- function(
Expand Down
44 changes: 22 additions & 22 deletions R/ggnet.R
Original file line number Diff line number Diff line change
Expand Up @@ -139,34 +139,34 @@
#' # Small function to display plots only if it's interactive
#' p_ <- GGally::print_if_interactive
#'
#' library(network)
#' if (require(network) && require(sna)) {
#' # random adjacency matrix
#' x <- 10
#' ndyads <- x * (x - 1)
#' density <- x / ndyads
#' m <- matrix(0, nrow = x, ncol = x)
#' dimnames(m) <- list(letters[1:x], letters[1:x])
#' m[row(m) != col(m)] <- runif(ndyads) < density
#' m
#'
#' # random adjacency matrix
#' x <- 10
#' ndyads <- x * (x - 1)
#' density <- x / ndyads
#' m <- matrix(0, nrow = x, ncol = x)
#' dimnames(m) <- list(letters[1:x], letters[1:x])
#' m[row(m) != col(m)] <- runif(ndyads) < density
#' m
#' # random undirected network
#' n <- network::network(m, directed = FALSE)
#' n
#'
#' # random undirected network
#' n <- network::network(m, directed = FALSE)
#' n
#' ggnet(n, label = TRUE, alpha = 1, color = "white", segment.color = "black")
#'
#' ggnet(n, label = TRUE, alpha = 1, color = "white", segment.color = "black")
#' # random groups
#' g <- sample(letters[1:3], 10, replace = TRUE)
#' g
#'
#' # random groups
#' g <- sample(letters[1:3], 10, replace = TRUE)
#' g
#' # color palette
#' p <- c("a" = "steelblue", "b" = "forestgreen", "c" = "tomato")
#'
#' # color palette
#' p <- c("a" = "steelblue", "b" = "forestgreen", "c" = "tomato")
#' p_(ggnet(n, node.group = g, node.color = p, label = TRUE, color = "white"))
#'
#' p_(ggnet(n, node.group = g, node.color = p, label = TRUE, color = "white"))
#'
#' # edge arrows on a directed network
#' p_(ggnet(network(m, directed = TRUE), arrow.gap = 0.05, arrow.size = 10))
#' # edge arrows on a directed network
#' p_(ggnet(network(m, directed = TRUE), arrow.gap = 0.05, arrow.size = 10))
#' }
ggnet <- function(
net,
mode = "fruchtermanreingold",
Expand Down
78 changes: 39 additions & 39 deletions R/ggnet2.R
Original file line number Diff line number Diff line change
Expand Up @@ -198,57 +198,57 @@
#' # Small function to display plots only if it's interactive
#' p_ <- GGally::print_if_interactive
#'
#' library(network)
#' if (require(network) && require(sna)) {
#' # random adjacency matrix
#' x <- 10
#' ndyads <- x * (x - 1)
#' density <- x / ndyads
#' m <- matrix(0, nrow = x, ncol = x)
#' dimnames(m) <- list(letters[1:x], letters[1:x])
#' m[row(m) != col(m)] <- runif(ndyads) < density
#' m
#'
#' # random adjacency matrix
#' x <- 10
#' ndyads <- x * (x - 1)
#' density <- x / ndyads
#' m <- matrix(0, nrow = x, ncol = x)
#' dimnames(m) <- list(letters[1:x], letters[1:x])
#' m[row(m) != col(m)] <- runif(ndyads) < density
#' m
#' # random undirected network
#' n <- network::network(m, directed = FALSE)
#' n
#'
#' # random undirected network
#' n <- network::network(m, directed = FALSE)
#' n
#' p_(ggnet2(n, label = TRUE))
#' p_(ggnet2(n, label = TRUE, shape = 15))
#' p_(ggnet2(n, label = TRUE, shape = 15, color = "black", label.color = "white"))
#'
#' p_(ggnet2(n, label = TRUE))
#' p_(ggnet2(n, label = TRUE, shape = 15))
#' p_(ggnet2(n, label = TRUE, shape = 15, color = "black", label.color = "white"))
#' # add vertex attribute
#' x = network.vertex.names(n)
#' x = ifelse(x %in% c("a", "e", "i"), "vowel", "consonant")
#' n %v% "phono" = x
#'
#' # add vertex attribute
#' x = network.vertex.names(n)
#' x = ifelse(x %in% c("a", "e", "i"), "vowel", "consonant")
#' n %v% "phono" = x
#' p_(ggnet2(n, color = "phono"))
#' p_(ggnet2(n, color = "phono", palette = c("vowel" = "gold", "consonant" = "grey")))
#' p_(ggnet2(n, shape = "phono", color = "phono"))
#'
#' p_(ggnet2(n, color = "phono"))
#' p_(ggnet2(n, color = "phono", palette = c("vowel" = "gold", "consonant" = "grey")))
#' p_(ggnet2(n, shape = "phono", color = "phono"))
#' if (require(RColorBrewer)) {
#'
#' if (require(RColorBrewer)) {
#' # random groups
#' n %v% "group" <- sample(LETTERS[1:3], 10, replace = TRUE)
#'
#' # random groups
#' n %v% "group" <- sample(LETTERS[1:3], 10, replace = TRUE)
#' p_(ggnet2(n, color = "group", palette = "Set2"))
#'
#' p_(ggnet2(n, color = "group", palette = "Set2"))
#' }
#'
#' }
#'
#' # random weights
#' n %e% "weight" <- sample(1:3, network.edgecount(n), replace = TRUE)
#' p_(ggnet2(n, edge.size = "weight", edge.label = "weight"))
#' # random weights
#' n %e% "weight" <- sample(1:3, network.edgecount(n), replace = TRUE)
#' p_(ggnet2(n, edge.size = "weight", edge.label = "weight"))
#'
#' # edge arrows on a directed network
#' p_(ggnet2(network(m, directed = TRUE), arrow.gap = 0.05, arrow.size = 10))
#' # edge arrows on a directed network
#' p_(ggnet2(network(m, directed = TRUE), arrow.gap = 0.05, arrow.size = 10))
#'
#' # Padgett's Florentine wedding data
#' data(flo, package = "network")
#' flo
#' # Padgett's Florentine wedding data
#' data(flo, package = "network")
#' flo
#'
#' p_(ggnet2(flo, label = TRUE))
#' p_(ggnet2(flo, label = TRUE, label.trim = 4, vjust = -1, size = 3, color = 1))
#' p_(ggnet2(flo, label = TRUE, size = 12, color = "white"))
#' p_(ggnet2(flo, label = TRUE))
#' p_(ggnet2(flo, label = TRUE, label.trim = 4, vjust = -1, size = 3, color = 1))
#' p_(ggnet2(flo, label = TRUE, size = 12, color = "white"))
#' }
ggnet2 <- function(
net,
mode = "fruchtermanreingold",
Expand Down
10 changes: 4 additions & 6 deletions R/ggnetworkmap.R
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,11 @@
#' @importFrom dplyr bind_rows
#' @importFrom utils installed.packages
#' @examples
#' library(dplyr)
#' # small function to display plots only if it's interactive
#' p_ <- GGally::print_if_interactive
#'
#' invisible(lapply(c("ggplot2", "maps", "network", "sna"), base::library, character.only = TRUE))
#'
#' ## Example showing great circles on a simple map of the USA
#' if (require(airports) && require(network) && require(sna)) {
#' if (require(dplyr) && require(network) && require(sna) &&
#' require(airports) && require(maps)) {
#' dms_to_number <- function(dms) {
#' parts <- strsplit(dms, "-")[[1]]
#' degrees <- as.numeric(parts[1])
Expand Down Expand Up @@ -113,7 +110,8 @@
#' data(twitter_spambots)
#'
#' # create a world map
#' world <- fortify(map("world", plot = FALSE, fill = TRUE))
#' map_data_fn <- if (packageVersion("ggplot2") >= "4.0.0") ggplot2::map_data else ggplot2::fortify
#' world <- map_data_fn(map("world", plot = FALSE, fill = TRUE))
#' world <- ggplot(world, aes(x = long, y = lat)) +
#' geom_polygon(aes(group = group),
#' color = "grey65",
Expand Down
Loading
Loading