Agrosel
Agrosel

Reputation: 539

R: Is it possible to combine a lattice xy plot with a ggplot?

I'm trying to create a basketball shot chart, and I've come to enjoy the look of a lattice shot chart plot, but it seems that I am unable to combine (or, place on top of) it with my ggplot court design. Is there anyway to do this? Or do I have to end up using the court as a raster image in the background (which is already giving me fits due to guessing and checking the image's coordinates)?

Here is a sample for the dat data frame

      location_x location_y points
1         5.5       22.1      2
2         6.0       24.1      2
3         6.1       39.4      2
4        25.3       38.7      0
5         8.0       24.4      2
6         8.8       12.7      0
7         9.0        6.0      0
8        10.6       31.6      0
9         4.2       47.5      0
10        4.3        8.9      2

EDIT: Below is my code, thanks to the help of the post: Using both color and size attributes in Hexagon Binning (ggplot2). The geom_path line is what's being used to draw the court. The error that I am currently getting is:

Error: Don't know how to add o to a plot

dat = mod_shots[mod_shots$player_id == 398068, ]

lattice_plot = xyplot(location_x~location_y, data = dat, panel = function(x,y,...)
{
  hbin = hexbin(dat$location_y, dat$location_x, xbins=40, IDs=TRUE)
  mtrans = hexTapply(hbin, dat$points, sum, na.rm=TRUE)
  cols = rev(heat.colors(7))
  grid.hexagons(hbin, style='lattice',
                minarea=0.1,maxarea=3,
                border="NA",
                pen=cols[mtrans+1])
})

ggplot() + geom_path(data = court_points,
          aes(x = x, y = y, z = NULL, group = desc, linetype = dash),
          color = "#000004") + lattice_plot

Upvotes: 0

Views: 706

Answers (1)

baptiste
baptiste

Reputation: 77096

Here's a dubious strategy: place the lattice panel as an annotation layer inside ggplot. I've made the lattice layer semi-transparent for illustration (burn blending mode of sorts).

enter image description here

library(grid) 
library(lattice) 
library(ggplot2) 

ghost_grob <- function(m, ...){
  grob(m=m, cl="ghost") 
}

preDrawDetails.ghost <- function(x){
  pushViewport(viewport(xscale = c(0, 1 + ncol(x$m)), yscale = 
                          c(0, 1 + nrow(x$m))))
}
postDrawDetails.ghost <- function(x){
  upViewport(1)
}

drawDetails.ghost <- function(x, recording){
  panel.levelplot(col(x$m), row(x$m), x$m, alpha.regions = 0.5,
                  subscripts=TRUE, at = do.breaks(range(x$m), 30)) 
}

grid.newpage() 
gpanel <- ghost_grob(volcano)
# gpanel <- rectGrob()
# grid.draw(gpanel)

ggplot(faithfuld, aes(waiting, eruptions)) +
  theme_minimal() + 
  scale_x_continuous(expand=c(0,0)) +
  scale_y_continuous(expand=c(0,0)) +
  geom_raster(aes(fill = density), interpolate = TRUE) +
  scale_fill_gradient(low = "white", high="black") +
  annotation_custom(gpanel, xmin = -Inf, xmax=Inf, ymin=-Inf, ymax=Inf)

Adding a layer of hexagons requires some understanding of the grid functions provided by hexbin. I don't have a clue how to use them, so I just adapted an example from ?hexpolygon for illustration. Obviously the scales and aspect ratio are nonsensical here.

ghost_grob <- function(x=runif(20, -2, 2), y=x + rnorm(20), ...){
  grob(x=x, y=y, cl="ghost") 
}

preDrawDetails.ghost <- function(x){
  addBit <- function(bnds, f = 0.05) bnds + c(-f, f) * diff(bnds)
  sc <- addBit(rxy <- range(x$x, x$y))
  pushViewport(plotViewport(.1+c(4,4,2,1), xscale = sc, yscale = sc))
}
postDrawDetails.ghost <- function(x){
  upViewport(1)
}

drawDetails.ghost <- function(x, recording){
  require(hexbin)
  hexpolygon(x$x,x$y, hexcoords(dx = 0.1, sep=NULL), border = "blue", fill=NA)
}


grid.newpage() 
gpanel <- ghost_grob()
# gpanel <- rectGrob()
# grid.draw(gpanel)

ggplot(faithfuld, aes(waiting, eruptions)) +
  theme_bw() + 
  scale_x_continuous(expand=c(0,0)) +
  scale_y_continuous(expand=c(0,0)) +
  geom_raster(aes(fill = density), interpolate = TRUE) +
  scale_fill_gradient(low = "white", high="black") +
  annotation_custom(gpanel, xmin = -Inf, xmax=Inf, ymin=-Inf, ymax=Inf) 

enter image description here

Upvotes: 1

Related Questions