## Challenge I long struggled with a convenient means of adding images, primarily logos, to maps and charts made in `ggplot`. All the approaches just seemed clunky, it was hard to size the and place the logo, or clipping had to be turned off, or the plot had to be saved and then reloaded to add the logo. Then I came across the `ggpmisc` package by Pedro Aphalo () which has a couple really nice functions `geom_grob_npc` and `geom_plot_npc` that make adding images/logos/ggplot objects to ggplot maps and charts so simple. Below I illustrate a simple wrapper for easy logo placement. ## `add_image` function Quick function that serves as a wrapper around `ggpmisc::geom_grob_npc` for placing images or logos on ggplot objects. I have used this for adding objects (such a context mini-globes) to maps, and logos to both maps and charts The `npc` functionality is really nice for relative placement and sizing is easy. Note: The real breakthrough here is nothing I have written, but the really useful `ggpmisc` package. ### Packages ``` r library(png) library(ggplot2) library(dplyr) library(palmerpenguins) library(tibble) library(ggpmisc) ``` ### Function to add image to ggplot object Lots of extraneous fluff in here for positioning and differential positioning for maps and charts. I have found this useful, but all of this is really just a wrapper around `geom_grob_npc` ``` r add_image <- function(plot_object, image_object, img_rel_size = 0.3, xloc = NA, yloc = NA, img_position = "lowerright", img_just = "inside") { # is it a map or a chart? is_map <- "crs" %in% names(plot_object$coordinates) image_ <- image_object # ------------------------------------ # CHARTS: # specify logo location (which corner) # ------------------------------------ if (is_map == FALSE) { if (is.na(xloc) & is.na(yloc)) { if (img_position == "upperleft") { x_ <- 0 y_ <- 1 } else if (img_position == "upperright") { x_ <- 1 y_ <- 1 } else if (img_position == "lowerright") { x_ <- 1 y_ <- 0 } else if (img_position == "lowerleft") { x_ <- 0 y_ <- 0 } else if (img_position == 'center') { x_ <- 0.5 y_ <- 0.5 } else { break } } else if (!is.na(xloc) & !is.na(yloc)) { x_ <- xloc y_ <- yloc } else { break } # ------------------------------------ # specify logo justification # ------------------------------------ if (img_just == "center") { vjust_ <- "center" hjust_ <- "center" } if (img_just == "outside") { if (img_position == "upperleft") { vjust_ <- "bottom" hjust_ <- "left" } else if (img_position == "upperright") { vjust_ <- "bottom" hjust_ <- "right" } else if (img_position == "lowerright") { vjust_ <- "top" hjust_ <- "right" } else if (img_position == "lowerleft") { vjust_ <- "top" hjust_ <- "left" } } if (img_just == "inside") { if (img_position == "upperleft") { vjust_ <- "top" hjust_ <- "left" } else if (img_position == "upperright") { vjust_ <- "top" hjust_ <- "right" } else if (img_position == "lowerright") { vjust_ <- "bottom" hjust_ <- "right" } else if (img_position == "lowerleft") { vjust_ <- "bottom" hjust_ <- "left" } } } # ------------------------------------ # MAPS: # specify logo location (which corner) # ------------------------------------ else { if (img_position == "upperleft") { vjust_ <- "bottom" hjust_ <- "left" } else if (img_position == "upperright") { vjust_ <- "bottom" hjust_ <- "right" } else if (img_position == "lowerright") { vjust_ <- "top" hjust_ <- "right" } else if (img_position == "lowerleft") { vjust_ <- "top" hjust_ <- "left" } else { break } # ------------------------------------ # specify logo justification and placement # ------------------------------------ if (is.na(xloc) & is.na(yloc)) { if (img_just == "inside") { if (img_position == "upperleft") { x_ <- 0.02 y_ <- 0.8 } else if (img_position == "upperright") { x_ <- 0.98 y_ <- 0.8 } else if (img_position == "lowerright") { x_ <- 0.98 y_ <- 0.2 } else if (img_position == "lowerleft") { x_ <- 0.02 y_ <- 0.2 } else if (img_position == 'center') { x_ <- 0.5 y_ <- 0.5 } } else if (img_just == "outside") { if (img_position == "upperleft") { x_ <- 0 y_ <- 0.9 } else if (img_position == "upperright") { x_ <- 1 y_ <- 0.9 } else if (img_position == "lowerright") { x_ <- 1 y_ <- 0.08 } else if (img_position == "lowerleft") { x_ <- 0 y_ <- 0.08 } else if (img_position == 'center') { x_ <- 0.5 y_ <- 0.5 } } else if (img_just == "center") { stop("Center justification on maps not supported") } } else if (!is.na(xloc) & !is.na(yloc)) { x_ <- xloc y_ <- yloc } else { break } } location_df <- tibble::tibble( x = x_, y = y_, width = img_rel_size, height = img_rel_size, grob = list(ggplot2::ggplotGrob(ggplot() + annotation_custom(image_) + theme_void())) ) plot_object + ggpmisc::geom_grob_npc( data = location_df, aes( label = grob, npcx = x, npcy = y, vp.width = width, vp.height = height ), vjust = vjust_, hjust = hjust_ ) } ``` ## Examples ### Load an image ``` r myurl <- "https://www.r-project.org/logo/Rlogo.png" z <- tempfile() download.file(myurl,z,mode="wb") pic <- readPNG(z) file.remove(z) # cleanup ``` FALSE [1] TRUE ``` r # convert to a rasterGrob rlogo <- grid::rasterGrob(pic, interpolate=TRUE) ``` ### Plot Examples ``` r plot <- ggplot() + geom_point( data = palmerpenguins::penguins, aes(flipper_length_mm, bill_length_mm, color = species) ) # place image in lower left, inside the plot panel add_image(plot_object = plot, image_object = rlogo, img_rel_size = 0.3, img_position = "lowerleft", img_just = "inside") ``` ![](add_image_files/figure-gfm/unnamed-chunk-4-1.png) ``` r # upper right, inside plot panel, and bigger add_image(plot_object = plot, image_object = rlogo, img_rel_size = 0.5, img_position = "upperright", img_just = "inside") ``` ![](add_image_files/figure-gfm/unnamed-chunk-5-1.png) ``` r # place logo in the center of the plot add_image(plot_object = plot, image_object = rlogo, img_rel_size = 0.3, img_position = 'center', img_just = "center") ``` ![](add_image_files/figure-gfm/unnamed-chunk-6-1.png) ``` r # place logo off-center add_image(plot_object = plot, image_object = rlogo, img_rel_size = 0.3, xloc = 0.8, yloc = 0.5, img_just = "center") ``` ![](add_image_files/figure-gfm/unnamed-chunk-7-1.png) ``` r # place logo under the plot on right side add_image(plot_object = plot + theme(plot.margin = margin(1, 1, 20, 1, unit = "mm")), image_object = rlogo, img_rel_size = 0.3, img_position = "lowerright", img_just = "outside") ``` ![](add_image_files/figure-gfm/unnamed-chunk-8-1.png) ``` r # combining img_position and xloc/yloc for alternate placement # pipe the plot into the add_image function (plot + theme(plot.margin = margin(1, 20, 1, 1, unit = "mm"))) %>% add_image( plot_object = ., image_object = rlogo, img_rel_size = 0.3, yloc = 0, xloc = 1, img_position = "lowerleft" ) ``` ![](add_image_files/figure-gfm/unnamed-chunk-9-1.png) ### Add to map ``` r land_sf <- rnaturalearth::ne_countries(scale = 110, returnclass = 'sf') ``` ``` r (ggplot() + geom_sf(data = land_sf) + theme_minimal()) %>% add_image(plot_object = ., img_rel_size = 0.2, image_object = rlogo, img_position = 'upperright', img_just = 'outside') ``` ![](add_image_files/figure-gfm/unnamed-chunk-11-1.png)