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")
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)
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