8
votes

With ggplot::geom_point we are able to set any character for plotting symbols using scale_shape_manual. I am coming with an example which demonstrates the purpose: use triangles to make a heatmap with two values in each cell:

require(ggplot2)

data <- data.frame(
    val = rnorm(40),
    grp = c(rep('a', 20), rep('b', 20)),
    x   = rep(letters[1:4], 5),
    y   = rep(letters[1:5], 4)
)

p <- ggplot(data, aes(x = x, y = y, color = val, shape = grp)) +
    geom_point(size = 18) +
    scale_shape_manual(values=c("\u25E4","\u25E2")) +
    theme_minimal() +
    theme(panel.grid = element_blank())

ggsave('triangle-tiles.pdf', device = cairo_pdf, width = 4.1, height = 3.5)

triangle heatmap with geom_point

This works fine if the font used for the symbols has these special characters. Otherwise apparently fails. I am aware that we can explicitely define font and get the same result with geom_text:

require(dplyr)

data <- data %>% mutate(sym = ifelse(grp == 'a', "\u25E4", "\u25E2"))

p <- ggplot(data, aes(x = x, y = y, color = val, label = sym)) +
    geom_text(size = 18, family = 'DejaVu Sans') +
    theme_minimal() +
    theme(
        panel.grid = element_blank()
    )

ggsave('triangle-tiles-2.pdf', device = cairo_pdf, width = 4.1, height = 3.5)

However the fact that also in geom_point these are characters coming from a typeface makes me really curious what is the way to overwrite the default.

I checked the grob of this plot trying to follow this example and found the points this way:

gr <- ggplotGrob(p)
gr[['grobs']][[6]]$children$geom_point

Here we have x, y, size, lwd (used in example above) etc but no typeface. Also I am wondering how to find directly and automatically the grob of the points from the root grob, e.g. with grid::getGrob, e.g. in the cited example grid::grid.edit finds them.

I found some promising code here which uses editGtable, a method I could not find in any package, maybe is an old one. Then I tried editGrob with no success:

font <- gpar(fontfamily = 'DejaVu Sans', fontsize = 14)
editGrob(gr[['grobs']][[6]], 'geom_point.points', grep = TRUE, global = TRUE, gp = font)
1
theme(text=element_text(family="DejaVu Sans")).eipi10
thanks @eipi10, this I have already tried and does not effect the plotting symbols, only the ticklabels, titles, etcdeeenes
I think very related: stackoverflow.com/questions/52902946/… and stackoverflow.com/questions/1395323/fonts-in-r-plots It's probably the "device's proper font", which you can set with family when calling the device. With ggsave, you would just add the font family with family = .... Unfortunately I am currently struggling with unicode characters on my Mac (similar to here stackoverflow.com/questions/12768176/…) so I am not able to post nice example imagestjebo

1 Answers

1
votes

The following is a bit of a hack, but you can wrap a pointlayer in a new class that assigns the fontfamily to the graphical parameters of a points. In the example below, the new class calls the parental methods for drawing the points in the layer and the key and then assigns the fontfamily to the graphical parameters.

require(ggplot2)
#> Loading required package: ggplot2

point_with_family <- function(layer, family) {
  old_geom <- layer$geom
  new_geom <- ggproto(
    NULL, old_geom,
    draw_panel = function(self, data, panel_params, coord, na.rm = FALSE) {
      pts <- ggproto_parent(GeomPoint, self)$draw_panel(
        data, panel_params, coord, na.rm = na.rm
      )
      pts$gp$fontfamily <- family
      pts
    },
    draw_key = function(self, data, params, size) {
      pts <- ggproto_parent(GeomPoint, self)$draw_key(
        data, params, size
      )
      pts$gp$fontfamily <- family
      pts
    }
  )
  layer$geom <- new_geom
  layer
}

data <- data.frame(
  val = rnorm(40),
  grp = c(rep('a', 20), rep('b', 20)),
  x   = rep(letters[1:4], 5),
  y   = rep(letters[1:5], 4)
)

p <- ggplot(data, aes(x = x, y = y, color = val, shape = grp)) +
  point_with_family(geom_point(size = 18), "DejaVu Sans") +
  scale_shape_manual(values=c("\u25E4","\u25E2")) +
  theme_minimal() +
  theme(panel.grid = element_blank())

ggsave('triangle-tiles-2.pdf', plot = p, device = cairo_pdf, width = 4.1, height = 3.5)

Created on 2021-08-29 by the reprex package (v2.0.0)

enter image description here

With a fontfamily that doesn't support the unicode characters:

enter image description here