Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inserting an image to ggplot outside the chart area

Tags:

r

ggplot2

Is it possible to add an image to ggplot chart which will be outside chart area?

I know it is possible to add images to the chart using annotate_raster and annotate_custom, however they both add images inside the chart. I need to add company logo in the upper right corner above the chart - at the title level.

Example of adding image using annotate_custom: Inserting an image to ggplot2

UPDATE: Following recommendations from user1317221_G, I'm able to put image outside.

library(png)
library(grid)
library(ggplot2)
img <- readPNG(system.file("img", "Rlogo.png", package="png"))

g <- rasterGrob(img, interpolate=TRUE)
plt <- qplot(1:10, 1:10, geom="blank") +
      opts(title = 'Title') + 
      geom_point() 
plt2 <- plt + annotation_custom(g, xmin=9, xmax=10, ymin=10.5, ymax=11.25)

gt <- ggplot_gtable(ggplot_build(plt2))
gt$layout$clip[gt$layout$name == "panel"] <- "off"
grid.draw(gt)

i would like to put image automatically - determine xmin/xmax and ymin/ymax automatically. Using traditional graphics i can call par('usr') and get chart parameters, but this is not applicable to ggplot charts. Is there an easy way to determine plot area in ggplot? For example get sizes of plt and plug the values for limits into plt2

UPDATE2: This method also doesn't really work if you use faceting. For example I would like to put logo in the right corner at title level, in the following chart, and I get errors if I use method above.

d <- ggplot(diamonds, aes(carat, price, fill = ..density..)) + 
     xlim(0, 2) + 
     stat_binhex(na.rm = TRUE) + 
     labs(title = 'Title') +
     theme(aspect.ratio = 1) + 
     facet_wrap(~ color, scales = "free_x")
like image 652
ilya Avatar asked Sep 17 '12 16:09

ilya


1 Answers

When faceting, annotation_custom draws the annotation in all panels. Therefore, annotation-custom might not be the best way to go. Here are two attempts using functions from the grid package. Neither is entirely automatic, but you might be able to adapt one or the other to meet your needs. They set up a 2 X 2 grid, shown using the grid.show.layout() command. In the first, the faceted plot fills the entire panel, and the top right viewport contains the logo. It just so happens that in your plot, there is clear space for the logo. Note how layout.pos.row and layout.pos.col give the rows and columns occupied by a viewport within the layout.

library(ggplot2)
library(png)
library(grid)

# Get the logo
img <- readPNG(system.file("img", "Rlogo.png", package="png"))
g <- rasterGrob(img)

# Set the size of the viewport to contain the logo
size = unit(2, "cm")

# Get the graph
d <- ggplot(diamonds, aes(carat, price)) + 
     xlim(0, 2) + 
     stat_binhex(na.rm = TRUE) + 
     labs(title = 'Title') +
     theme(aspect.ratio = 1) + 
     facet_wrap(~ color, scales = "free_x")

# Set up the layout for grid 
heights = unit.c(size, unit(1, "npc") - size)
widths = unit.c(unit(1, "npc") - size, size)
lo = grid.layout(2, 2, widths = widths, heights = heights)
# Show the layout
grid.show.layout(lo)

# Position the elements within the viewports
grid.newpage()
pushViewport(viewport(layout = lo))

    # The plot
pushViewport(viewport(layout.pos.row=1:2, layout.pos.col = 1:2))
print(d, newpage=FALSE)
popViewport()

    # The logo
pushViewport(viewport(layout.pos.row=1, layout.pos.col = 2))
print(grid.draw(g), newpage=FALSE)
popViewport()
popViewport()

# To save the object
g = grid.grab()

grid.newpage()
grid.draw(g)

The title does not entirely align with the logo. One fix is to remove the title from the ggplot, draw a separate textGrob that contains the title, then position the textGrob in the top left viewport beside the viewport that contains the logo.

# Get the logo
img <- readPNG(system.file("img", "Rlogo.png", package="png"))
g <- rasterGrob(img)

# Set the size of the viewport to contain the logo
size = unit(2, "cm")

# Get the graph
d <- ggplot(diamonds, aes(carat, price)) + 
     xlim(0, 2) + 
     stat_binhex(na.rm = TRUE) + 
     # labs(title = 'Title') +
     theme(aspect.ratio = 1) + 
     facet_wrap(~ color, scales = "free_x")

# and the title
title = textGrob("Title", gp = gpar(face = "bold", cex = 2))

# Set up the layout for grid 
heights = unit.c(size, unit(1, "npc") - size)
widths = unit.c(unit(1, "npc") - 1.5*size, size)
lo = grid.layout(2, 2, widths = widths, heights = heights)
# Show the layout
grid.show.layout(lo)

# Position the elements within the viewports
grid.newpage()
pushViewport(viewport(layout = lo))

    # The plot
pushViewport(viewport(layout.pos.row=2, layout.pos.col = 1:2))
print(d, newpage=FALSE)
popViewport()

    # The logo
pushViewport(viewport(layout.pos.row=1, layout.pos.col = 2))
print(grid.draw(g), newpage=FALSE)
popViewport()

    # The title
pushViewport(viewport(layout.pos.row=1, layout.pos.col = 1))
print(grid.draw(title), newpage=FALSE)
popViewport()
popViewport()

# To save the object
g = grid.grab()

grid.newpage()
grid.draw(g)

enter image description here

like image 174
Sandy Muspratt Avatar answered Oct 16 '22 05:10

Sandy Muspratt