I am trying to produce weighted density plots with R using the ggplot2 package and save them as .png files. In my code I am producing 100-1000 of these plots, with different geographical coordinates.
The problem is that, if my data set is even 1500 points, then the ggsave function becomes really slow. Then it approximately takes 100s to save one of these plots. From what I have understood, the computational inefficiency comes from the fact that the ggplot2 objects I'm plotting are grids and the ggsave has to print them before saving them.
So, I'm asking is there any way to make the saving of these ggplot2 objects more efficient? I mean any other way than lowering the resolution of the kde2d density estimate, which would indeed make the data frame to be plotted smaller.
I have provided a minimum working example, where I produce one of the .png files. When you use system.time() around the ggsave function, you will see that it takes around 100s to perform it.
library(MASS)
library(ggplot2)
library(grid)
x <- runif(1550, 0, 100)
y <- runif(1550, 0, 100)
wg <- runif(1550, 0, 1)
data <- data.frame(x, y, wg)
source("C:/Users/cpt2avo/Documents/R/kde2dweighted.r")
dens <- kde2d.weighted(data$x, data$y, data$wg)
dfdens <- data.frame(expand.grid(x=dens$x, y=dens$y), z=as.vector(dens$z))
p <- ggplot(data, aes(x = x, y = y)) + stat_contour(data = dfdens, geom = "polygon", bins = 20, alpha = 0.2, aes(x = x, y = y, z = z, fill = ..level..)) + scale_fill_continuous(low = "green", high = "red") + scale_alpha(range = c(0,1), limits = c(0.5, 1), na.value = 0) + labs(x = NULL, y = NULL) + theme(axis.title = element_blank(), axis.text = element_blank(), axis.ticks = element_blank(), axis.line = element_blank(), plot.margin = unit(c(0,0,-0.5,-0.5), "line"), panel.border = element_blank(), panel.grid = element_blank(), panel.margin = unit(c(0,0,0,0), "mm"), legend.position = "none", plot.background = element_rect(fill = "transparent", colour = NA), panel.background = element_blank())
system.time(ggsave(p, file = "C:/Users/cpt2avo/Documents/R/example.png", width = 2, height = 2, units = "in", dpi = 128))
The kde2d.weighted is a function for doing 2d weighted kernel density estimates.
kde2d.weighted <- function (x, y, w, h, n = 25, lims = c(range(x), range(y))) {
nx <- length(x)
if (length(y) != nx)
stop("data vectors must be the same length")
if (length(w) != nx & length(w) != 1)
stop("weight vectors must be 1 or length of data")
gx <- seq(lims[1], lims[2], length = n) # gridpoints x
gy <- seq(lims[3], lims[4], length = n) # gridpoints y
if (missing(h))
h <- c(bandwidth.nrd(x), bandwidth.nrd(y));
if (missing(w))
w <- numeric(nx)+1;
h <- h/4
ax <- outer(gx, x, "-")/h[1] # distance of each point to each grid point in x-direction
ay <- outer(gy, y, "-")/h[2] # distance of each point to each grid point in y-direction
z <- (matrix(rep(w,n), nrow=n, ncol=nx, byrow=TRUE)*matrix(dnorm(ax), n, nx)) %*% t(matrix(dnorm(ay), n, nx))/(sum(w) * h[1] * h[2]) # z is the density
return(list(x = gx, y = gy, z = z))
}
You can either print directly a ggplot into PNG/PDF files or use the convenient function ggsave() for saving a ggplot. The default of ggsave() is to export the last plot that you displayed, using the size of the current graphics device. It also guesses the type of graphics device from the extension.
The plot can be saved in the eps format using the ggplot. save() method, which takes as argument the string name of the plot.
2.1. The default size of the saved image is equal to the size of Plots pane (the “graphics device”) in RStudio, which can be found with dev. size() . Notice that the result of dev. size() and the message we receive when saving the plot with ggsave() give the same dimensions.
In most cases ggsave() is the simplest way to save your plot, but sometimes you may wish to save the plot by writing directly to a graphics device. To do this, you can open a regular R graphics device such as png() or pdf() , print the plot, and then close the device using dev. off() .
@AntonvSchantz I ran into the same problems as you did, am having very similar experiences. Indeed, it's exporting to high-resolution png via ggsave() which makes this process slow. My resolution was to go with exporting into pdf, by doing something like:
Above your plot creation
pdf(paste("plots/my_filename", rn , ".pdf", sep = ""), width = 11, height = 8)
Below your plot creation:
dev.off()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With