I am learning to code in ggplot2. I wish to create a new geom which makes something complex – not a simple polygon. Say, a rectangle with a point in the middle.
When I am defining my new geom object, say GeomFafik, I need to specify the function draw_panel
(or draw_group
, or whichever) which returns a grob. Here is how it looks now (based on the extending ggplot2 vignette:
GeomFafik <- ggproto("GeomFafik",
Geom,
required_aes=c("xmin", "ymin", "xmax", "ymax"),
default_aes=aes(shape=19, colour="black"),
draw_key=draw_key_blank(),
draw_panel=function(data, panel_params, coord) {
coords <- coord$transform(data, panel_params)
# how can I combine grob1 with grob2 and
# return the result?
grob1 <- grid::rectGrob(coords$xmin, coords$ymin,
width=coords$xmax - coords$xmin,
height=coords$ymax - coords$ymin,
gp=gpar(col=coord$colour))
grob2 <- grid::pointsGrob(x=coords$xmin + (coords$xmax - coords$xmin)/2,
y=coords$ymin + (coords$ymax - coords$ymax)/2,
gp=gpar(col=coord$colour))
})
Am I right that I should build a grob using grob()
or gTree()
from grid
? Or is there a ggplot2
way of doing that (similar to zeroGrob
)? And if grid
, then which of the two should I use? And where can I find examples? The manual page doesn't really say much.
OK, so that was easier than I thought. The solution is to use gTree as follows (thanks to this example):
GeomFafik <- ggproto("GeomFafik",
Geom,
required_aes=c("xmin", "ymin", "xmax", "ymax"),
default_aes=aes(shape=19, colour="black"),
draw_key=draw_key_blank(),
draw_panel=function(data, panel_params, coord) {
coords <- coord$transform(data, panel_params)
w <- coords$xmax - coords$xmin
h <- coords$ymax - coords$ymin
x <- coords$xmin + w/2
y <- coords$ymin + h/2
grob1 <- grid::rectGrob(x, y, width=w, height=h,
gp=gpar(col=coord$colour))
grob2 <- grid::pointsGrob(x=x, y=y,
gp=gpar(col=coord$colour))
grid::gTree("fafik_grob", children=grid::gList(grob1, grob2))
})
geom_fafik <- function(mapping = NULL, data = NULL, stat = "identity",
position = "identity", na.rm = FALSE, show.legend = NA,
inherit.aes = TRUE, ...) {
layer(
geom = GeomFafik, mapping = mapping, data = data, stat = stat,
position = position, show.legend = show.legend, inherit.aes = inherit.aes,
params = list(na.rm = na.rm, ...)
)
}
Result, which is what I wanted: