Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add a border around a chart created via arrange.grid in gridExtra encompassing a set ggplot2 scatter plots

I'm using the code below:

# Libs
require(ggplot2); require(gridExtra); require(grid)

# Generate separate charts
chrts_list_scts <- list()

# Data
data("mtcars")

# A
chrts_list_scts$a <- ggplot(mtcars) +
  geom_point(size = 2, aes(x = mpg, y = disp,
                           colour = as.factor(cyl))) +
  geom_smooth(aes(x = mpg, y = disp),
              method = "auto") +
  xlab("MPG") +
  ylab("Disp") +
  theme_bw() +
  theme(panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        legend.position = "none")

# B
chrts_list_scts$b <- ggplot(mtcars) +
  geom_point(size = 2, aes(x = mpg, y = drat,
                           colour = as.factor(cyl))) +
  geom_smooth(aes(x = mpg, y = drat),
              method = "auto") +
  xlab("MPG") +
  ylab("Drat") +
  theme_bw() +
  theme(panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        legend.position = "none")

# C
chrts_list_scts$c <- ggplot(mtcars) +
  geom_point(size = 2, aes(x = mpg, y = qsec,
                           colour = as.factor(cyl))) +
  geom_smooth(aes(x = mpg, y = qsec),
              method = "auto") +
  xlab("MPG") +
  ylab("QSEC") +
  guides(colour = guide_legend(title = "cyl")) +
  theme_bw() +
  theme(panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        legend.position = "bottom",
        legend.key = element_rect(colour = NA))

# Arrange grid
png(filename = "chrts.PNG", width = 6,
    height = 10, units = 'in', res = 300)
title_text <- c("mtcars")
chrts_list_scts$all_scts <- grid.arrange(chrts_list_scts$a,
                                         chrts_list_scts$b,
                                         chrts_list_scts$c,
                                         top =
                                           textGrob(label = title_text,
                                                    gp = gpar(
                                                      fontsize = 14,
                                                      font = 2)))
dev.off()
rm(title_text)

To generate the following chart:

first chart

I'm interested in adding border around that chart, as in the picture below:

with border

Attempts

I tried to address this request via adding polygonGrob in the code:

chrts_list_scts$all_scts <- grid.arrange(chrts_list_scts$dep_work,
                                         chrts_list_scts$chld_work,
                                         chrts_list_scts$pens,
                                         polygonGrob(x = c(0,0.5,1.05),
                                                     y = c(0,0.5,1.05)
                                                     ),
                                         top =
                                           textGrob(label = title_text,
                                                    gp = gpar(
                                                      fontsize = 14,
                                                      font = 2)))

but this generates a pointless chart with one line across in the bottom. I had a look at the seeming similar discussion on SO but it wasn't clear to me how to arrive at a working solution.

Side requirements

In addition to generating the border, I would like to:

  1. Be able to exercise some control over the border aesthetics, like changing size and colour of the border.
  2. Ideally, I would like to encapsulate this solution within the arrange.grid call. So at the object chrts_list_scts$all_scts has all elements including charts and neat border around all of them.

I will be happy to accept solutions that address the major requirements with respect to the border only, if there is a suggested solution that matches the remaining two points it will be even nicer.

like image 851
Konrad Avatar asked Nov 25 '15 15:11

Konrad


People also ask

How do you make a grid on a graph in R?

Creating a Grid of Plots To do this, you use the parameter value mfrow=c(x,y) where x is the number of rows that you wish to have in your plot and y is the number of columns. When you plot, R will place each plot, in order by row within the grid that you define using mfrow .

What is Grid Arrange function in R?

If layout parameters are ommitted altogether, grid. arrange() will calculate a default number of rows and columns to organise the plots. More complex layouts can be achieved by passing specific dimensions (widths or heights), or a layout matrix defining the position of each plot in a rectangular grid.

How to arrange multiple plots in ggplot2?

To arrange multiple ggplot2 graphs on the same page, the standard R functions - par() and layout() - cannot be used. The basic solution is to use the gridExtra R package, which comes with the following functions: grid. arrange() and arrangeGrob() to arrange multiple ggplots on one page.

What is a Grob in Ggplot?

First off a grob is just short for “grid graphical object” from the low-level graphics package grid; Think of it as a set of instructions for create a graphical object (i.e. a plot). The graphics library underneath all of ggplot2's graphical elements are really composed of grob's because ggplot2 uses grid underneath.


1 Answers

1) Using the iris example (but further simplified) from the link provided in the question just add the last line. Modify the gpar(...) components (and possibly the width and height) to get different aesthetics. (This is not encapsulated in the grid.arrange call.)

library(ggplot2)
library(grid)
library(gridExtra)

g <- ggplot(iris, aes(Sepal.Width, Sepal.Length)) + geom_point()
grid.arrange(g, g, ncol=2)


# next line adds border
grid.rect(width = .98, height = .98, gp = gpar(lwd = 2, col = "blue", fill = NA))

(continued after plot)

screenshot

2) This is a variation of solution (1) in which on the plus side encapsulates both the graphics and border in the gt gTree by creating grobs to hold each. On the other hand it does involve some additional complexity:

grid.newpage()
ga <- arrangeGrob(g, g, ncol = 2)
gb <- rectGrob(height = .98, width = .98, gp = gpar(lwd = 2, col = "blue", fill = NA)) # border, no fill
gt <- gTree(children = gList(ga, gb))
grid.draw(gt)
like image 183
G. Grothendieck Avatar answered Oct 01 '22 14:10

G. Grothendieck