I frequently need several different sizes of the same ggplot2 chart output to png files. The size of each png file is easy enough to generate by using variables for the output height and width in pixels. For the ggplot2 part I use variables for the size of fonts and certain other elements and set up a simple loop that changes those variables in each pass. This all works as expected and is a tribute to the flexibility of R and ggplot2.
Most of the time I am creating one of a small number of chart types, most of which do not vary. Accordingly I thought it would make sense to create a simple function that looks after the boilerplate code and returns the plots from ggplot2 in a list. All I need to do is pass to the function the data frame, the name of the column I want used in the chart and a couple of other variables. The loop creates a name for the plot, calls ggplot and assigns the result to an element in the list. On the second pass it changes the font size variables but otherwise behaves identically.
However, the font sizes do not seem to be getting picked up by ggplot. Specifically, I am using variables to control the size of geom_text(), the size of the x and y axis text and the title of the plot. When I print the contents of the list after it is returned from the function, the geom_text() size is changing as one would expect, but the other two elements are unchanged when they should be different. (Note that in the code below I am using two 'medium' and 'large' png files with the same pixel size but usually one would be twice as large as the other - this is just for illustrative purposes.)
And the second image, which should have different title and axis text sizes to the first, but does not:
Because this approach works fine when used 'in-line' as part of a normal code chunk I can only assume that there is some straightforward problem with the way I am calling or perhaps refreshing the function that is causing the problem. Any help much appreciated.
I haven't used named functions in R before and I am a casual programmer rather than a professional, so apologies in advance for the dodgy code below.
# create test data
set.seed(12345)
mydf <- data.frame(passdate=seq(as.Date("1995/1/1"), by="month", length.out=204),passval=runif(204, min=25, max=100),ignoreval=runif(204, min=-21, max=-2))
myplots <- list()
myplots <- chart_high_mom(mydf,'passdate','passval','1995-02-01','2011-12-31',"My title here")
# first chart
mywidth = 700
myheight = 600
png(filename = "chart1.png", width = 700, height = 600, units = "px", res = NA)
print(myplots[[1]])
dev.off()
# second chart - this intended to be twice as large when bugs fixed
png(filename = "chart2.png", width = 700, height = 600, units = "px", res = NA)
print(myplots[[2]])
dev.off()
# end of calling code
chart_high_mom <- function(
x = NULL, # a data frame containing the data to plot
datecol, # name of column holding yyyy-mm-dd date series
valcol, # name of column holding value to use for calculation
fstartdate, # date in yyyy-mm-dd format specifying first date to plot
fenddate, # date in yyyy-mm-dd format specifying last date to plot
ftitle # title to add to plot
)
{
require(gdata)
require(xts)
require(ggplot2)
require(lubridate)
# strip the data frame down
x <- subset(x,select = c(datecol,valcol))
colnames(x) <- c('mydate','myval')
# create year and month columns
x$year <- as.numeric(format(as.Date(x$mydate), format="%Y"))
x$month <- as.numeric(format(as.Date(x$mydate), format="%m"))
# create month-on-month change column
mydata.xts <- xts(x$myval,order.by=x$mydate)
x$myvalmom <- diff(mydata.xts,lag=1)/lag(mydata.xts,1)
plotlist <- list()
for (i in 1:2) { # loop to create plot with two different sets of font sizes
plotname <- paste("myplot", i, sep = "")
if (i == 1) {
fontsize <- 8
titlesize <- 16
geomtextsize <- 4
ftitle <- "medium"
}
if (i == 2) {
fontsize <- 24
titlesize <- 28
geomtextsize <- 5
ftitle <- "large"
}
print(paste("i = ",i," and fontsize = ",fontsize," and plot = ",plotname,sept=""))
plotlist[[plotname]] <- ggplot(x[x$mydate>=fstartdate & x$mydate<=fenddate,],
aes(x=month(mydate,label=TRUE),y=year(mydate), fill = myvalmom, label = sprintf("%1.1f%%", 100*myvalmom))) +
scale_y_date(major="years", format="%Y") +
geom_tile() +
geom_text(data=x[x$mydate>=fstartdate & x$mydate<=fenddate,],size = geomtextsize,colour = "black") +
scale_fill_gradient2(low = "blue", high = "red",midpoint=0) +
scale_x_discrete(expand=c(0,0)) +
scale_y_reverse(breaks=1980:2012, labels=1980:2012, expand=c(0,0) ) +
opts(
axis.text.y = theme_text(size = fontsize, colour = "grey50"),
axis.text.x = theme_text(size = fontsize, colour = "grey50"),
plot.title = theme_text(size = titlesize),
title = ftitle,
panel.grid.minor = theme_blank(),
axis.ticks = theme_blank(),
panel.grid.major = theme_blank(),
axis.title.y = theme_blank(),
axis.title.x = theme_blank(),
panel.background = theme_rect(fill = "transparent",colour = NA),
legend.position = "none"
)
}
return(plotlist)
}
Define your plot functions first (so they can accept the parameters you will be changing:
chart_high_mom <- function(fontsize, titlesize, geomtextsize, ftitle,
x = NULL, # a data frame containing the data to plot
datecol, # name of column holding yyyy-mm-dd date series
valcol, # name of column holding value to use for calculation
fstartdate, # date in yyyy-mm-dd format specifying first date to plot
fenddate # date in yyyy-mm-dd format specifying last date to plot
) {
# strip the data frame down
x <- subset(x,select = c(datecol,valcol))
colnames(x) <- c('mydate','myval')
# create year and month columns
x$year <- as.numeric(format(as.Date(x$mydate), format="%Y"))
x$month <- as.numeric(format(as.Date(x$mydate), format="%m"))
# create month-on-month change column
mydata.xts <- xts(x$myval,order.by=x$mydate)
x$myvalmom <- diff(mydata.xts,lag=1)/lag(mydata.xts,1)
plotlist <- list()
print(paste("i = ",i," and fontsize = ",fontsize," and titlesize = ",titlesize,sep=""))
thisplot <- ggplot(x[x$mydate>=fstartdate &
x$mydate<=fenddate,],
aes(x=month(mydate,label=TRUE),y=year(mydate),
fill = myvalmom, label = sprintf("%1.1f%%", 100*myvalmom))) +
scale_y_date(major="years", format="%Y") +
geom_tile() +
geom_text(data=x[x$mydate>=fstartdate &
x$mydate<=fenddate,],size = geomtextsize,
colour = "black") +
scale_fill_gradient2(low = "blue", high = "red",midpoint=0) +
scale_x_discrete(expand=c(0,0)) +
scale_y_reverse(breaks=1980:2012, labels=1980:2012, expand=c(0,0) ) +
force(opts(axis.text.y =
theme_text(size = force(fontsize), colour = "grey50"),
axis.text.x = theme_text(size = force(fontsize), colour = "grey50"),
plot.title = theme_text(size = titlesize),
title = ftitle,
panel.grid.minor = theme_blank(),
axis.ticks = theme_blank(),
panel.grid.major = theme_blank(),
axis.title.y = theme_blank(),
axis.title.x = theme_blank(),
panel.background = theme_rect(fill = "transparent",colour = NA),
legend.position = "none"
))
return(thisplot)
}
.... then call them. And call them with the parameter values you want:
set.seed(12345)
mydf <- data.frame(passdate=seq(as.Date("1995/1/1"), by="month", length.out=204),passval=runif(204, min=25, max=100),ignoreval=runif(204, min=-21, max=-2))
myplots <- list()
for (i in 1:2) { # loop to create plot with two different sets of font sizes
if (i == 1) {
print(fontsize <- 8)
print(titlesize <- 32)
print(geomtextsize <- 4)
print(ftitle <- "medium");
myplots[[1]] <-chart_high_mom(fontsize= fontsize , titlesize= titlesize , geomtextsize= geomtextsize , ftitle= ftitle , x=mydf, 'passdate', 'passval', '1995-02-01', '2011-12-31')
png(filename = "chart1.png", width = 700, height = 600, units = "px", res = NA)
print(myplots[[1]])
dev.off() }
if (i == 2) {
fontsize <- 24
titlesize <- 12
geomtextsize <- 5
ftitle <- "large";
myplots[[2]] <-chart_high_mom(fontsize= fontsize , titlesize= titlesize , geomtextsize= geomtextsize , ftitle= ftitle , x=mydf, 'passdate', 'passval', '1995-02-01', '2011-12-31')
png(filename = "chart2.png", width = 700, height = 600, units = "px", res = NA)
print(myplots[[2]])
dev.off() } }
# end of calling code
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