产生相同视觉输出的 2 个 ggplot 对象不一定相同,但有时评估它们的等价性很有用。我们应该怎么做 ?
看起来 ggplot2 不支持该功能,因此最好有一个社区解决方案,也许在某个地方有一个打包函数。
请在下面找到我自己的看法。请随意改进它或贡献不同的方法。
预期的 :
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
equivalent_ggplot(p1, p2 + geom_blank())
#> [1] TRUE
Run Code Online (Sandbox Code Playgroud)
我不确定它有多强大,但我一直在使用它:
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
Run Code Online (Sandbox Code Playgroud)
创建于 2024-02-09,使用reprex v2.0.2
比较 svgs 是另一种选择,它比上面的慢两倍(还不错,我预计会慢一些),但我怀疑复杂的绘图相对时间差会更大。
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)
}
Run Code Online (Sandbox Code Playgroud)