I'm not sure how robust it is but I've been using this:
equivalent_ggplot <- function(x, y) {
# ggplot_table triggers a blank plot that can't be silenced so we divert it
# not sure if pdf() is the most efficient
pdf(tempfile(fileext = ".pdf"))
x_tbl <- suppressWarnings(ggplot2::ggplot_gtable(ggplot2::ggplot_build(x)))
y_tbl <- suppressWarnings(ggplot2::ggplot_gtable(ggplot2::ggplot_build(y)))
dev.off()
# we could probably do a better index equivalency check than just scrubbing
# them off, but I haven't figured out how it works
x_unlisted <- gsub("\\d+", "XXX", unlist(x_tbl))
y_unlisted <- gsub("\\d+", "XXX", unlist(y_tbl))
names(x_unlisted) <- gsub("\\d+", "XXX", names(x_tbl))
names(y_unlisted) <- gsub("\\d+", "XXX", names(y_tbl))
identical(x_unlisted, y_unlisted)
}
library(ggplot2)
p1 <- ggplot(cars, aes(dist, speed)) + ggplot2::geom_point()
p2 <- ggplot(cars, aes(dist, speed)) + geom_point() + scale_x_continuous(breaks = seq(0, 125, 25))
equivalent_ggplot(p1, p2)
#> [1] TRUE
Created on 2024-02-09 with reprex v2.0.2
Comparing the svgs is another option, that's twice slower than the above (not that bad, I was expecting slower) but I suspect with complex plots the relative time difference will be bigger.
equivalent_ggplot2 <- function(x, y) {
tmp1 <- tempfile(fileext = ".svg")
tmp2 <- tempfile(fileext = ".svg")
suppressMessages(ggplot2::ggsave(tmp1, x))
suppressMessages(ggplot2::ggsave(tmp2, y))
tools::md5sum(tmp1) == tools::md5sum(tmp2)
}
ggplot2::geom_point()
andgeom_point()
don't create the same object for instance. In order to test that our generated code constructs functionally identical plots we need this feature. – Incidencewrap_plots()
, to test whether they should be merged. Possibly a peek under the hood would be informative. Surprised Thomas didn't mention this when replying to your GitHub issue. – Panther