如何在cowplot的plot_grid中刷新png设备生成完全一致图像?
plot_grid and ggsave I get it—you’ve got two plots that look identical to the human eye, but diff says they’re different, and you can’t replicate the issue in a reprex. Frustrating! Let’s break down the likely culprits and fix this:
1. Wipe the Slate Clean: Reset Your Plotting Environment
Hidden state in the plotting device is probably the biggest culprit here. Even if you can’t see it, previous plot calls might leave behind viewports, cached objects, or modified graphics parameters that tweak the final PNG output slightly.
- Close all open devices before each plotting sequence to start fresh:
while (!is.null(dev.list())) dev.off() - Clear the grid page right before generating your final plot (critical for cowplot, which uses the grid system):
grid.newpage() - Reset base graphics parameters if you’re mixing base and ggplot/cowplot code:
par(mfrow = c(1,1), mar = c(5,4,4,2) + 0.1)
2. Lock Down Every Single Parameter
Even tiny, seemingly insignificant differences in plot settings can create pixel-level discrepancies. Make sure:
- All
ggsavearguments are identical across both runs:height,width,dpi,units, and explicitly specify the device to avoid system defaults:ggsave("graph1.png", plot = your_final_plot, height = 10, width = 10, dpi = 600, device = "png") - Every
plot_gridparameter matches: Double-checkrel_heights,rel_widths,nrow,ncol,align, andaxisvalues. A typo (like yoursecond_graph_on_purpusevssecond_graph_on_purpose—though that’s probably a typo here) or a forgotten argument can sneak in. - No reused objects have hidden changes: Don’t rely on intermediate objects (like your
pvariable) that might have been modified by previous code. Regenerate the entire plot chain from scratch each time—from data loading to the finalplot_gridcall.
3. Check if It’s Just Metadata (Not Pixel Differences)
Sometimes diff flags differences in PNG metadata (like creation timestamps or software version) rather than actual pixel content. Verify if the pixels are truly identical with the png package:
library(png) img1 <- readPNG("graph1.png") img2 <- readPNG("graph2.png") all.equal(img1, img2)
If this returns TRUE, the visuals are identical—you just need to standardize the metadata. Use the Cairo PNG device for more consistent output:
ggsave("graph1.png", plot = your_final_plot, device = function(filename) { png(filename, type = "cairo-png", dpi = 600, height = 10, width = 10, units = "in") })
Cairo tends to produce cleaner, more consistent PNGs with less variable metadata.
4. Force a Full Regeneration of Plot Objects
Plot objects in ggplot/cowplot can cache internal state. Instead of reusing a pre-built p or semifinal object, rebuild the entire plot every time you want to save it. This ensures no cached values from previous runs leak into the final output.
For example, instead of reusing p from a prior run, re-run all the steps to create pmatrix, legend, and p each time before saving.
If you’re still hitting issues in your long code, try commenting out sections incrementally to isolate where the hidden state is being introduced—chances are it’s a stray plot call or parameter tweak that’s leaving a footprint you can’t see.
内容的提问来源于stack exchange,提问作者user2338823

