1

I am not entirely sure if these kind of questions are allowed at SO, as I have no reproducible data at the moment.

My question is in regards to how one might go about creating a scatterplot of raster images in R. I am not familiar with any packages that allow you to do this. This is the only example I have come across so far in my search. Essentially, this is what I would like to do, however, I am wondering if it's possible for R to simply take the input data and plot the image rather than be fed coordinates in my plot area.

My end goal is to create raster image scatterplots of sports teams using their logos instead of labels. My first thought is to create a data frame including team name, X variable, Y variable, and .png image URL location.

Here is an example of what I am ultimately hoping to do. I'm not sure what program the OP uses, but obviously I would like to do something like this in R.

enter image description here


UPDATE

With the help of Greg Snow's suggestion, I was able to reproduce his example with my own logos.

enter image description here

medavis6
  • 843
  • 10
  • 32
  • 2
    check [here](http://stackoverflow.com/a/20734985/4964651) – mtoto Feb 01 '16 at 22:19
  • 1
    Here is another `ggplot2` answer that might help get you started: http://stackoverflow.com/a/27641888/645206 – bdemarest Feb 01 '16 at 23:16
  • @bdemarest I followed your examples provided, but could only manage to plot one logo at a time, as they did. When I tried to loop over a list of raster images, I get an error: `no applicable method for 'as.raster' applied to an object of class "list"`. How would I go about using `ggplot()` with multiple logos? – medavis6 Feb 03 '16 at 20:44

1 Answers1

3

The the my.symbols and ms.image functions in the TeachingDemos package are one possible starting place. There is an example on the help page for ms.image that shows how to use the R logo as the plotting symbol. Currently it only does one image at a time, so you could either start with a blank plot and loop through the set of images, or a wrapper function can be written that takes a list of images and an indicator of which to plot. Here is a first stab at a wrapper function:

ms.image2 <- function(imgs, transpose=TRUE, 
                      which=1, ...) {
  ms.image(imgs[[which]], transpose=transpose, ...)
}

Then we can create a list of images with code like:

require(png)
img1 <- readPNG(system.file("img", "Rlogo.png", package="png"))
logos <- list( img1, img1[76:1,,], img1[,100:1,],
               img1[76:1,100:1,], img1[,,c(3:1,4)])

These are all variations on the logo, but for your example you could pass a vector of file names of the .png files to lapply to produce a similar list.

Now we can run my.symbols like this (though obviously you will use real data rather than random numbers for the locations):

my.symbols( runif(10), runif(10), ms.image2, 
            MoreArgs=list(imgs=logos), which=rep(1:5,2),
            inches=0.3, symb.plots=TRUE, add=FALSE)

And that produces a plot along the lines of your example:

enter image description here

Edit

For a speed up you can use rasterImage, here is some new code that ran in about half the time as the above (compared using microbenchmark):

ms.rasterImage <- function(imgs, which=1, ...) {
  rasterImage(imgs[[which]], -1, -1, 1, 1)
}

logos2 <- list(as.raster(img1), as.raster(img1[76:1,,]),
               as.raster(img1[,100:1,]), 
               as.raster(img1[76:1,100:1,]),
               as.raster(img1[,,c(3:1,4)])
    )

my.symbols( runif(10), runif(10), ms.rasterImage, 
            MoreArgs=list(imgs=logos2), which=rep(1:5,2),
            inches=0.3, symb.plots=TRUE, add=FALSE)

And here is some code using ggplot2 based on the link in the comment above, but using the list of logos:

ggplot(mtcars, aes(mpg, wt)) + 
  mapply(function(xx, yy, i) 
    annotation_raster(logos[[i]], xmin=xx-1, xmax=xx+1, ymin=yy-0.2, ymax=yy+0.2),
    mtcars$mpg, mtcars$wt, mtcars$gear-2) 

And mainly for my curiosity, here are the timings:

> microbenchmark(
+   my.symbols( mtcars$mpg, mtcars$wt, ms.image2, 
+               MoreArgs=list(imgs=logos), which=mtcars$gear-2,
+               inches=0.3, symb.plots=TRUE, add=FALSE),
+   my.symbols( mtcars$mpg, mtcars$wt, ms.rasterImage, 
+               MoreArgs=list(imgs=logos2), which=mtcars$gear-2,
+               inches=0.3, symb.plots=TRUE, add=FALSE),
+   plot(ggplot(mtcars, aes(mpg, wt)) + 
+          mapply(function(xx, yy, i) 
+            annotation_raster(logos[[i]], xmin=xx-1, xmax=xx+1, ymin=yy-0.2, ymax=yy+0.2),
+            mtcars$mpg, mtcars$wt, mtcars$gear-2) )
+ )
Unit: milliseconds

                      min       lq     mean   median        uq       max neval cld
       ms.image  518.9137 530.5549 661.9333 545.3890  751.7116 1737.7430   100  b 
 ms.rasterImage  158.7097 162.4493 244.6673 171.6103  381.6499  544.1656   100 a  
        ggplot2  478.3005 606.3831 896.8793 772.7210 1359.8888 1714.5647   100   c
Greg Snow
  • 48,497
  • 6
  • 83
  • 110
  • Thanks for the great example. I was able to reproduce your code with my own logos as displayed above. I have one last question about the feasibility/possibility of implementing this with Shiny. Would this kind of thing be possible/feasible? My computer struggles enough to produce one plot at a time with the images. Can I use the code provided to make reactive tables that adjust positions of logos or would this take to much computation on my/user/Shiny's end? – medavis6 Feb 03 '16 at 16:18
  • @medavis6, I don't see any reason that the plot would not work with shiny, but the viewer may not like the delay if it is really slow. Using a lower resolution image may be one way to speed up the plot. Also, `ms.image` currently uses the `image` function, it may run faster to switch to using the `rasterImage` function (convert everything to rasters one time first). – Greg Snow Feb 03 '16 at 21:11
  • Thanks again. I'm currently in the process of trying to use @bdemarest's suggestion using `ggplot()` which edits the images using `rasterGrob()` and `annotation_custom()`. My only problem is figuring out how to loop over 30 images where the examples show 2 different images, tops. [For example](https://i.gyazo.com/ef1223af1da3b318c9563f1056e8fd6a.png). – medavis6 Feb 03 '16 at 21:15
  • 1
    @medavis6, I added a couple of other examples, one uses `rasterImage` which cuts the time to create the plot about in half (on my computer). I also modified the ggplot2 code from the link in the comment to use the list of logos and show that code above. Both work nicely, the `my.symbols` takes care of the aspect ratio for you. You need to work that out for yourself with the ggplot2 approach. – Greg Snow Feb 03 '16 at 21:40
  • Thanks for all the help. [I was able to get it all to work now!](https://i.gyazo.com/6b5904386d0f56a26259e25db835ae0a.png) – medavis6 Feb 03 '16 at 22:01