I don't know how to use custom point markers that work with geom_point (although you could create your own geom , as suggested by @baptiste). However, if you are ready to bear some pain in coding, you can use annotation_custom to create something similar to what you would get with geom_point . The painful part is that you need to do some manual settings (although you could probably create program logic that will handle some of them for you if you are going to do this). The plot also appears very slowly. However, it was great to crack it.
Download the packages and get two images that will become our markers:
library(ggplot2) library(RCurl) library(jpeg) library(grid) ## Image 1 URL1 = "http://www.entertainmentearth.com/images/AUTOIMAGES/QMSER0179lg.jpg" serenity = readJPEG(getURLContent(URL1)) ## Image 2 URL2 = "http://cdn.pastemagazine.com/www/articles/2010/03/12/malcolm_reynolds.jpg" mal = readJPEG(getURLContent(URL2)) # Crop the mal image mal = mal[40:250,,] ## Turn images into raster grobs serenity = rasterGrob(serenity) mal = rasterGrob(mal) # Make the white background transparent in the serenity image serenity$raster[serenity$raster=="#FFFFFF"] = "#FFFFFF00"
Create fake data and set up a schedule:
# Create fake data df = data.frame(x=rep(1:4,2), y=c(1,1,2,4,6.5,5,5.5,4.8), g=rep(c("s","m"),each=4))
Now, instead of geometry, use annotation_custom to build images as point markers. annotation_custom seems to work only with one point at a time, and not with a vector of points, so we will use a for loop to build each point. We have two different images that we want to build, so we will use a separate cycle for each of them:
a=0.8 for (i in rownames(df[df$g=="s",])) { p = p + annotation_custom(serenity, df[i,"x"]-a,df[i,"x"]+a,df[i,"y"]-a,df[i,"y"]+a) } b=0.4 for (i in rownames(df[df$g=="m",])) { p = p + annotation_custom(mal, df[i,"x"]-b,df[i,"x"]+b,df[i,"y"]-b,df[i,"y"]+b) }
Finally, add the legend and turn off cropping so that the legend appears on the last chart:
a = 0.8*a b = 0.8*b p = p + coord_cartesian(xlim=c(0,5), ylim=c(0,7)) + theme(plot.margin=unit(c(1,10,1,1),"lines")) + annotation_custom(serenity, 5.8-a,5.8+a,3.4-a,3.4+a) + annotate(geom="text", x=5.8+0.5, y=3.4, label="Serenity", hjust=0) + annotation_custom(mal, 5.8-b,5.8+b,4.6-b,4.6+b) + annotate(geom="text", x=5.8+0.5, y=4.6, label="Mal", hjust=0) # Turn off clipping p <- ggplot_gtable(ggplot_build(p)) p$layout$clip <- "off" grid.draw(p)

UPDATE: The new ggimage package may make this a little easier. The following is an example. There are several things that I would like to improve as a result of the conspiracy.
Changing the aspect ratio of the screen also changes the aspect ratio of the images, while I would prefer that the images remain in their own aspect ratio.
The Serenity image has a white background that covers the plot grid and the Mal image (since Serenity is displayed after Mal). In the above example, I made the white background transparent. However, even when I saved the raster vultures created above as jpeg (so that I could use the version of Serenity with a transparent background) and reloaded them (instead of getting the images directly from the URLs, as I do below), the Serenity image was still White background.
The legend does not use images as โpoint markersโ and instead has an empty space where there will usually be markers.
Perhaps future versions of the package will provide additional flexibility related to these problems, or perhaps there is already a way that I do not know to solve these problems.
df = data.frame(x=rep(1:4,2), y=c(1,1,2,4,6.5,5,5.5,4.8), Firefly=rep(c("Serenity","Mal"),each=4), image=rep(c("http://www.entertainmentearth.com/images/AUTOIMAGES/QMSER0179lg.jpg", "http://cdn.pastemagazine.com/www/articles/2010/03/12/malcolm_reynolds.jpg"), each=4)) ggplot(df, aes(x, y)) + geom_line(aes(group=Firefly)) + geom_image(aes(image=image, size=Firefly)) + theme_bw() + scale_size_manual(values=c(0.1,0.15)) + coord_fixed(ratio=2/3, xlim=c(0.5, 4.5), ylim=c(0,7))
