user2808302
user2808302

Reputation:

Plotting geom_point() on top of geom_hex() in ggplot2()

I am trying to plot a background dataset (below: "bDat") as hexagonal bins, and then overlay points from a different dataset (below: "points"). I would like to accomplish this using ggplot2() and keeping the syntax as similar as possible to the MWE provided below.

I am able to get the hexagonal background plotted with the below MWE:

library(ggplot2)
library(hexbin)

set.seed(1)
bDat <- data.frame(Group1 = rnorm(100,0,1), Group2 = rnorm(100,0,1))
points <- data.frame(Group1 = rnorm(10,0.5,1), Group2 = rnorm(10,0.5,1))
maxVal = max(max(bDat), max(points))
minVal = min(min(bDat), min(points))
maxRange = c(minVal, maxVal)
xbins=10
buffer = maxRange[2]/xbins
xChar = "Group1"
yChar = "Group2"
x = bDat[,c(xChar)]
y = bDat[,c(yChar)]
h <- hexbin(x=x, y=y, xbins=xbins, shape=1, IDs=TRUE, xbnds=maxRange, ybnds=maxRange)
hexdf <- data.frame (hcell2xy (h),  hexID = h@cell, counts = h@count)
attr(hexdf, "cID") <- h@cID

ggplot(hexdf, aes(x=x, y=y, fill = counts, hexID=hexID)) +
  geom_hex(stat="identity") + 
  geom_abline(intercept = 0, color = "red", size = 0.25) +
  coord_cartesian(xlim = c(maxRange[1], maxRange[2]), ylim = c(maxRange[1], maxRange[2]))

However, when I change the last command in the above MWE to try to overlay the points, I receive an error that the object hexID is not found:

ggplot(hexdf, aes(x=x, y=y, fill = counts, hexID=hexID)) +
  geom_hex(stat="identity") + 
  geom_abline(intercept = 0, color = "red", size = 0.25) + 
  coord_cartesian(xlim = c(maxRange[1], maxRange[2]), ylim = c(maxRange[1], maxRange[2])) + 
  geom_point(data = points, aes(x=Group1, y=Group2))

Error in eval(expr, envir, enclos) : object 'hexID' not found

Any suggestions would be appreciated!

Upvotes: 0

Views: 806

Answers (1)

Peter
Peter

Reputation: 7790

The default behavior of the geoms it to inherit the aesthetics already specified in the ggplot object. In your example,

ggplot(hexdf, aes(x=x, y=y, fill = counts, hexID=hexID))

will result, by default, all geom_* calls to use these values for the x, y, fill, and hexID aesthetics. This works well when all the layers use the same data set and aesthetics.

However, when geom_point(data = points, aes(x = Group1, y = Group2)) is called, the fill = counts and hexID = hexID is implicitly passed to geom_point as well.

By seting the inherit.aes = FALSE the geom

overrides the default aesthetics, rather than combining with them. This is most useful for helper functions that define both data and aesthetics and shouldn't inherit behaviour from the default plot specification, e.g. ‘borders’.

From your first MWE, take

last_plot() + 
  geom_point(data = points, aes(x=Group1, y=Group2), inherit.aes = FALSE)

and the resulting plot is: enter image description here

Upvotes: 1

Related Questions