2

I am creating a list of (gg)plot objects and then trying to view all plots in a single graph. From the questions: How can I arrange an arbitrary number of ggplots using grid.arrange?, and How do I arrange a variable list of plots using grid.arrange?, I was hoping that the following code would do the trick (Skip to the last few lines for the code that actually does the multi-plot thing).

#!/usr/bin/Rscript
library(ggplot2)
library(reshape)
library(gridExtra)
args <- commandArgs(TRUE);
# Very first argument is the directory containing modelling results
setwd(args[1])
df = read.table('model_results.txt', header = TRUE)
df_actual = read.table('measured_results.txt', header = TRUE)
dfMerge = merge(df, df_actual, by = c("Clients", "MsgSize", "Connections"))

# All graphs should be stored in the directory pointed by second argument
setwd(args[2])

# Plot the results obtained from model for msgSize = 1, 1999
# and connections = 10, 15, 20, 25, 30, 50

msgSizes = c(1, 1999)
connVals = c(5, 10, 15, 20, 25, 30, 50)

cmp_df = data.frame(dfMerge$Clients, dfMerge$MsgSize, dfMerge$Connections, dfMerge$PThroughput, dfMerge$MThroughput)
colnames(cmp_df) = c("Clients", "MsgSize", "Connections", "ModelThroughput", "MeasuredThroughput")
cmp_df_melt = melt(cmp_df, id = c("Clients", "MsgSize", "Connections"))
colnames(cmp_df_melt) = c("Clients", "MsgSize", "Connections", "Variable", "Value")

plotList = list()
for (i in msgSizes) {
    msg_Subset = subset(cmp_df_melt, MsgSize == i)

    for (j in connVals) {
        plotData = subset(msg_Subset, Connections == j)

        filename = paste("Modelling.",i, ".", j, ".png", sep = '') 
        list_item = ggplot(data = plotData, aes(Clients, y = Value, color = Variable)) +
            geom_point() +
            geom_line() + 
            xlab("Number of Clients") +
            ylab("Throughput (in ops/second)") +
            labs(title = paste("Message Size = ", i, ", Connections = ", j), color = "Legend")

        plotList = c(plotList, list_item)
        # ggsave(file = filename)

    }
}

# Plot all graphs together
pdf("Summary.pdf")
list_len = length(plotList)
nCol = floor(sqrt(list_len))
do.call(grid.arrange, c(plotList, list(ncol = nCol)))
dev.off() 

Instead, I hit the following error:

Error in arrangeGrob(..., as.table = as.table, clip = clip, main = main,  : 
  input must be grobs!
Calls: do.call -> <Anonymous> -> grid.draw -> arrangeGrob
Execution halted

What am I doing wrong, especially since the two linked questions suggest the same thing? Also, what changes should be made to actually save the graph in a file?

3
  • Can't really test your code since you didn't supply sample data, but it looks like in the examples you cited plotList is a list. Commented Dec 11, 2013 at 22:53
  • Wild guess, but maybe changing to do.call(grid.arrange, c(plotList, ncol = nCol)) will help? Commented Dec 11, 2013 at 23:26
  • Also, try lapply(plotlist,class) just to confirm whether each element is actually a plot or not. Just in case. Commented Dec 11, 2013 at 23:27

2 Answers 2

5

Here is a minimal, reproducible example of your problem. It reproduces the error message and can be easily run by any interested users by pasting the code into a fresh R session. The error is caused by the unexpected behavior of plot_list = c(plot_list, new_plot).

library(ggplot2)
library(gridExtra)

dat = data.frame(x=1:10, y=1:10)

plot_list = list()
nplot = 3

for (i in seq(nplot)) {
    new_plot = ggplot(dat, aes(x=x, y=y)) +
               geom_point() +
               labs(title=paste("plot", i))
    plot_list = c(plot_list, new_plot)
}

png("plots.png", width=10, height=5, units="in", res=150)
do.call(grid.arrange, c(plot_list, list(ncol=nplot)))
dev.off()
# Error in arrangeGrob(..., as.table = as.table, clip = clip, main = main,  : 
#  input must be grobs!

The error is resolved by wrapping new_plot with list():

plot_list = c(plot_list, list(new_plot))

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

4

As others have said, it's impossible to test your code as you do not provide sample data. However, grid.arrange(...) expects a list containing either grobs or ggplot objects. You are providing a list that has some number of ggplot objects, and a numeric. Did you try this?

do.call(grid.arrange, plotlist)    # untested

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.