Inserting an image to ggplot outside the chart area

前端 未结 1 1586
温柔的废话
温柔的废话 2020-12-09 12:39

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_

相关标签:
1条回答
  • 2020-12-09 12:58

    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

    0 讨论(0)
提交回复
热议问题