Save Ggplot Within a Function

Save ggplot with a function

You can use print() to save plots produced from ggplot2 to a file.

First, define your function to save plots:

savePlot <- function(myPlot) {
pdf("myPlot.pdf")
print(myPlot)
dev.off()
}

Create your plot:

 myPlot <- ggplot(ggplot(data=df.music, aes(x=music, y=number)) +
geom_bar(stat="identity") +
xlab(colnames(df.music)[1]) +
ylab(colnames(df.music)[2]) +
ylim(c(0,11)) +
ggtitle("Ulubiony typ muzyki wśród studentów")

And finally call the function:

savePlot(myPlot)

Alternatively, you could just use ggsave() after creating your plot:

ggsave(filename="myPlot.pdf", plot=myPlot)

Use of ggplot() within another function in R

As Joris and Chase have already correctly answered, standard best practice is to simply omit the meansdf$ part and directly refer to the data frame columns.

testplot <- function(meansdf)
{
p <- ggplot(meansdf,
aes(fill = condition,
y = means,
x = condition))
p + geom_bar(position = "dodge", stat = "identity")
}

This works, because the variables referred to in aes are looked for either in the global environment or in the data frame passed to ggplot. That is also the reason why your example code - using meansdf$condition etc. - did not work: meansdf is neither available in the global environment, nor is it available inside the data frame passed to ggplot, which is meansdf itself.


The fact that the variables are looked for in the global environment instead of in the calling environment is actually a known bug in ggplot2 that Hadley does not consider fixable at the moment.
This leads to problems, if one wishes to use a local variable, say, scale, to influence the data used for the plot:

testplot <- function(meansdf)
{
scale <- 0.5
p <- ggplot(meansdf,
aes(fill = condition,
y = means * scale, # does not work, since scale is not found
x = condition))
p + geom_bar(position = "dodge", stat = "identity")
}

A very nice workaround for this case is provided by Winston Chang in the referenced GitHub issue: Explicitly setting the environment parameter to the current environment during the call to ggplot.
Here's what that would look like for the above example:

testplot <- function(meansdf)
{
scale <- 0.5
p <- ggplot(meansdf,
aes(fill = condition,
y = means * scale,
x = condition),
environment = environment()) # This is the only line changed / added
p + geom_bar(position = "dodge", stat = "identity")
}

## Now, the following works
testplot(means)

save plots made by loop in a file

In the code you had shared:

for(i in 1:28) {
plot_i <- ggplot(Num, aes(Num[,i]))+ geom_histogram(fill="skyblue", col="Blue")+
ggtitle(names(Num)[i])+theme_classic()

ggplot2::ggsave(filename = paste0("plot_",i,".png"),plot_i, path = "E:/Folder1")

}

You are storing the plot object in the variable plot_i. You are not printing those plots. You need to insert, print(plot_i) statement before saving the plot using ggplot as follows:

for(i in 1:28) {
plot_i <- ggplot(Num, aes(Num[,i]))+ geom_histogram(fill="skyblue", col="Blue")+
ggtitle(names(Num)[i])+theme_classic()

print(plot_i)

ggplot2::ggsave(filename = paste0("plot_",i,".png"),plot_i, path = "E:/Folder1")

}

The reason why you need to print is because, ggsave defaults to save the last displayed plot, and by printing you actually display on the Rs display devices. In simpler words this is what ggsave does:

png('file_name.png') #it opens a graphics devices, can be other also like jpeg
print(plot_i) #displays the plot on graphics device
dev.off() #closes the graphic device

ggplot2 does not appear to work when inside a function R

It's an R FAQ -- you need print() around it, or a ggsave() which is particular to ggplot2.

From the FAQ:

7.22 Why do lattice/trellis graphics not work?

The most likely reason is that you forgot to tell R to display the
graph. Lattice functions such as xyplot() create a graph object, but
do not display it (the same is true of ggplot2 graphics, and Trellis
graphics in S-Plus). The print() method for the graph object produces
the actual display. When you use these functions interactively at the
command line, the result is automatically printed, but in source() or
inside your own functions you will need an explicit print() statement.

Use apply() to ggplot() to create and save individual jpegs

I think the main problem with the example you provided is that the loop is made over the "parks" vector, which only contains the levels of "Park_name". I think a better approach would be to loop over the data, subsetting by each "Park_name" entry.

I am also assuming that you have a column with the "units" variable (I added it in the plot as "Units"); however, if that is not the case, you may be able to create it using dplyr::separate. I hope you find this code useful!

# determine park levels
parks <- unique(data[,"Park_name"])

# lapply for each park entry
p <- lapply(parks, function(park) {

#Subset the data by the each entry in the parks vector
subdata <- subset(data,data$Park_name == park)

#Collapse the zone vector as a string
zones <- paste(unique(subdata[,"Zone"]),
collapse = " ")
##ggplot
ggplot(subdata, aes(x=as.factor(Year), y=Height_mm)) +
facet_grid(Zone~.) +
geom_point() +
#Add the title and y lab as variables defined by park name, zones and a column with unit information
labs(title = paste(subdata$Park_name, zones, sep = " "),
y = paste0("Height (", subdata$Units,")"),
x = "Year") +

stat_summary(fun.data="mean_cl_boot", color="red")

#Save the plot, define your folder location as "C:/myplots/"
ggsave(filename = paste0(folder, park,".jpeg"),
device = "jpeg",
width = 15,
height = 10,
units = "cm",
dpi = 200)
})

how to combine ggsave in a function of ggplot?

Use ggsave

invisible(by(df, df$ID, function(i) {
p <- ggplot(i, aes(Date, EC))+
geom_line() +
geom_point() +
ggtitle(unique(i$ID))
ggsave(sprintf("file%s.pdf", unique(i$ID)),p)
}))


Related Topics



Leave a reply



Submit