Reputation: 539
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
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).
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)
Upvotes: 1