如何测试 2 个 ggplots 功能相同?

Moo*_*per 8 r ggplot2

产生相同视觉输出的 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)

Moo*_*per 9

我不确定它有多强大,但我一直在使用它:

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)

  • 然而,“equivalent_ggplot(p1, p2 + geom_blank())”为 FALSE,有两个逐像素相同的图。 (2认同)