Search code examples
rraster

R: Creating list of png rasters, reading into grid.raster


This post is related to a question I asked a couple days ago, and specifically to this post (from which I borrowed the code below). I felt it warranted a new question because this is a new issue.

I am trying to graph in ggplot2 with custom images for geom_point, then paste those images into the legend. However, when I put the image rasters into a list, and reference elements of that list in grid.raster it throws an error. Is there are way to store png rasters in a list so they can be called from grid.raster later? Here's an example...

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

# Get image
img <- readPNG(system.file("img", "Rlogo.png", package="png"))

# Grab online image
url <- "https://www.rstudio.com/wp-content/uploads/2014/06/RStudio-Ball.png"
destfile <- "myfile.png"
r_studio <- download.file(url, destfile, mode="wb")
r_studio <- readPNG("myfile.png")

# Put images in list    
image_list <- list(img, r_studio)

# Plot
p = ggplot(mtcars, aes(mpg, disp, colour = factor(vs))) + 
  geom_point() +
  theme(legend.key.size = unit(1, "cm"))

# Get ggplot grob
gt = ggplotGrob(p)
grid.newpage()
grid.draw(gt)


# Search using regular expressions
Tree = as.character(current.vpTree())
pos = gregexpr("\\[key.*?\\]", Tree)
match = unlist(regmatches(Tree, pos))

match = gsub("^\\[(key.*?)\\]$", "\\1", match) # remove square brackets
match = match[!grepl("bg", match)]  # removes matches containing bg

# Loop through image list. Change the legend keys to images
for(i in 1:2){
 downViewport(match[i])
 grid.rect(gp=gpar(col = NA, fill = "white"))
 grid.raster(image_list[i], interpolate=FALSE)
 upViewport(0) 
}

When I run this last loop I get the following error

Error in UseMethod("as.raster") : 
 no applicable method for 'as.raster' applied to an object of class "list" 

I noticed that putting the images into a list changes the type from double to list, so I'm guessing this has something to do with it.

typeof(img)
[1] "double"
typeof(image_list[1])
[1] "list"

Solution

  • You are getting that error because of the way you are subsetting image_list when you do image_list[i], you need to go one level deeper by adding an extra pair of [] i.e., image_list[[i]] to get the array (image)

    library(png)
    library(ggplot2)
    library(grid)
    
    # Get image
    img <- readPNG(system.file("img", "Rlogo.png", package="png"))
    
    # Grab online image
    url <- "https://www.rstudio.com/wp-content/uploads/2014/06/RStudio-Ball.png"
    destfile <- "myfile.png"
    r_studio <- download.file(url, destfile, mode="wb")
    r_studio <- readPNG("myfile.png")
    
    #Create the object `img`: your example code above does not do this
    img <- r_studio
    
    # Put images in list    
    image_list <- list(img, r_studio)
    
    # Plot
    p = ggplot(mtcars, aes(mpg, disp, colour = factor(vs))) + 
      geom_point() +
      theme(legend.key.size = unit(1, "cm"))
    
    # Get ggplot grob
    gt = ggplotGrob(p)
    grid.newpage()
    grid.draw(gt)
    
    # Search using regular expressions
    Tree = as.character(current.vpTree())
    pos = gregexpr("\\[key.*?\\]", Tree)
    match = unlist(regmatches(Tree, pos))
    
    match = gsub("^\\[(key.*?)\\]$", "\\1", match) # remove square brackets
    match = match[!grepl("bg", match)]  # removes matches containing bg
    
    # Loop through image list. Change the legend keys to images
    for(i in 1:2){
     downViewport(match[i])
     grid.rect(gp=gpar(col = NA, fill = "white"))
     grid.raster(image_list[[i]], interpolate=FALSE)
     upViewport(0) 
    }