How to capture ggplot2 errors? - r

I'm generating pdf reports using ggplot2. Code looks something like this
pdf()
for (){
p <- ggplot(..)
print(p)
}
dev.off()
Sometimes because of the data quality ggplot fails to generate the plot. There could be multiple reasons, and we don't want to check all possible combinations for data failing. We simply want to check if ggplot fails - and continue. This is what I came up with - this works, but there are some issues.
library(ggplot2)
p <- ggplot(mtcars, aes(wt, mpg)) +
geom_point()
p.bad <- ggplot(mtcars, aes(wt, as.character(mpg))) +
geom_point() +
scale_y_continuous()
pdf()
a <- try(print(p), silent = TRUE) # double printing
if (class(a)!='try-error'){
print(p)
}
b <- try(print(p.bad), silent = TRUE)
if (class(b)!='try-error'){
print(p.bad)
}
dev.off()
try(print) - generates a chart if there is no error. Is there a way of preventing it? This will probably the best solution. If we do the following - there is no double printing, but second try(print) generates blank page.
pdf()
a <- try(print(p), silent = TRUE)
b <- try(print(p.bad), silent = TRUE)
dev.off()
Is there another way of finding out if ggplot will generate an error?

I suggest to use ggsave:
ttt <- function() {
require(ggplot2)
p.bad <- ggplot(mtcars, aes(wt, as.character(mpg))) +
geom_point() +
scale_y_continuous()
a <- try(ggsave("test.pdf",p.bad))
return("test")
}
ttt()
# Saving 12.9 x 9.58 in image
# Error : Discrete value supplied to continuous scale
# [1] "test"

Related

(R) Graphs in a loop and funktion are empty, even though they work when plottet standalone

So, I have a boxplot where i annotate the number of datapoint per plot and significance levels in letters above the plots. When plottet in a normal (?!?) workflow, they take about 1-2 seconds to plot in a X Window System Graphics (X11), the plot gets saved afterwards. When the plot-command is wrapped in a for-loop or called by a function, the X11-window stays empty and gets saved like that.
Here is a minimal example using mtcars, showcasing the same problem. Without context this example does not make sense.
library(ggplot2)
setwd("C:/")
output <- "C:/"
data <- mtcars
data$cyl <- as.factor(data$cyl)
#----normal plotting----
x11()
ggplot(data, aes(x = cyl, y = mpg))+
stat_boxplot(geom = "errorbar")+
geom_boxplot()
savePlot(paste0(output, "example_normal", ".tiff"), type = "tiff")
dev.off()
#----plotting throught a function----
my.plot <- function(x)
{
x11()
ggplot(x, aes(x = cyl, y = mpg))+
stat_boxplot(geom = "errorbar")+
geom_boxplot()
savePlot(paste0(output, "example_function", ".tiff"), type = "tiff")
dev.off()
}
my.plot(data)
Cheers
I had to post a print(ggplot(...)) around it to make it work in a for-loop.

What's the expression for partial derivative in ggplot()?

Is it possible to get the partial derivative symbol via expression() in ggplot2, e.g. to be used in axis labels?
I am talking about this symbol, often also refered to as 'del' or 'curly d': https://en.wikipedia.org/wiki/%E2%88%82
It has unicode number U+2202, but when I try to include it in ggplot, it fails:
a <- b <- rnorm(100)
plot.df <- data.frame(a,b)
ggplot(plot.df,aes(a,b)) +
geom_point() +
xlab(expression('\u2202'))
For comparison, using e.g. the plus/minus sign with unicode number U+00B1 works fine:
ggplot(plot.df,aes(a,b)) +
geom_point() +
xlab(expression('\u00b1'))
you can achieve this using the keyword partialdiff. using your example:
ggplot(plot.df,aes(a,b)) +
geom_point() +
xlab(expression(paste(partialdiff,"y","/",partialdiff,"x")))
This link provides some good reference on the matter.
Depending how far you want to go. You can eventually use TikzDevice library to save the plot directly as a tex.file. It might take longer to compile the graph but I find it more flexible.
library(tikzDevice)
tikz("/tmp/test.tex",standAlone = TRUE)
ggplot(plot.df,aes(a,b)) +
geom_point() +
xlab("$\\frac{\\partial{y}}{\\partial{x}}$")
dev.off()
With the ggtext package you can use HTML entities:
library(ggplot2)
library(ggtext)
a <- b <- rnorm(100)
plot.df <- data.frame(a,b)
ggplot(plot.df, aes(a,b)) +
geom_point() +
xlab("∂") +
theme(axis.title.x = element_markdown(size = 20))

plot(p) and plot(ggplot_gtable(ggplot_build(p))) don't seem to give same output when plot background is transparent

I have the following R ggplot code:
require(ggplot2)
require(ggthemes)
df <- data.frame(x=1:10, y=5*(1:10))
p <- ggplot(df, aes(x,y)) +
geom_point() +
theme_few() +
theme(plot.background = element_rect(fill='transparent', colour=NA), legend.position='top')
pdf('test.pdf', width=5, height=2)
plot(p)
plot(ggplot_gtable(ggplot_build(p)))
But I do get two different figures:
I like the first figure (i.e without the background grid outside panel area). However, I also need to use ggplot_build() for some other processing. Could you please help?
You could copy what ggplot2::print.ggplot does more directly. This seems to work.
pdf('test.pdf', width=5, height=2)
plot(p)
grid::grid.newpage()
grid::grid.draw(ggplot_gtable(ggplot_build(p)))
dev.off()

arbitrary number of plots for grid.arrange

I'm trying to plot an arbitrary number of bar plots with rmarkdown separated by 2 columns. In my example there will be 20 total plots so I was hoping to get 10 plots in each column, however, I can't seem to get this to work with grid.arrange
plot.categoric = function(df, feature){
df = data.frame(x=df[,feature])
plot.feature = ggplot(df, aes(x=x, fill = x)) +
geom_bar() +
geom_text(aes(label=scales::percent(..count../1460)), stat='count', vjust=-.4) +
labs(x=feature, fill=feature) +
ggtitle(paste0(length(df$x))) +
theme_minimal()
return(plot.feature)
}
plist = list()
for (i in 1:20){
plist = c(plist, list(plot.categoric(train, cat_features[i])))
}
args.list = c(plist, list(ncol=2))
do.call("grid.arrange", args.list)
When I knit this to html I'm getting the following output:
I was hoping I would get something along the lines of:
but even with this the figure sizes are still funky, I've tried playing with heights and widths but still no luck. Apologies if this is a long question
If you have all the ggplot objects in a list then you can easily build the two column graphic via gridExtra::grid.arrange. Here is a simple example that will put eight graphics into a 4x2 matrix.
library(ggplot2)
library(gridExtra)
# Build a set of plots
plots <-
lapply(unique(diamonds$clarity),
function(cl) {
ggplot(subset(diamonds, clarity %in% cl)) +
aes(x = carat, y = price, color = color) +
geom_point()
})
length(plots)
# [1] 8
grid.arrange(grobs = plots, ncol = 2)

write plots to png file

I can use ggplot2 to store the output of ggplot command to an object and call that object within grid.arrange to write to a file in an R script, as below:
p<-ggplot(x, aes(x=Date, y=Date)) + geom_bar(aes(x=Date,y=Data)
png("data.png", height=700, width=650)
grid.arrange(p, main=textGrob("Data"), gp=gpar(cex=2)
dev.off()
I am creating bunch of forecast graphs using plot but I cannot do the same thing. Any one has any suggestion how can I write the ouput of plot to a png file in a script?
We don't have data to work with and the questions not clear so here's an example of what I think the OP is after (separate plots for each plot) using the mtcars data set:
dat <- split(mtcars, mtcars$cyl)
lapply(dat, function(x) {
ggplot(x, aes(mpg, disp, colour=gear)) + geom_point()
}
)
#a way to get separate plots for each plot
plot2 <- function(theplot, name, ...) {
name <- paste0(name, ".png")
png(filename=name)
print(theplot)
dev.off()
} #plotting function
lapply(seq_along(dat), function(i) {
x <- dat[[i]]
z <- ggplot(x, aes(mpg, disp, colour=gear)) + geom_point()
plot2(z, name=paste0("TEST", names(dat)[i]))
}
)
data <- data.frame(x=1:10,y=rnorm(10))
p <- ggplot(data, aes(x,y)) + geom_point()
p
library(gridExtra)
Loading required package: grid
grid.arrange(p,p,p)
ggsave('~/Desktop/grid.png')
Does this approach not work with forecast graphs?

Resources