5

I would like o create my own labeller function to take input for facet labels, transform it to a string that contains math notation and then have ggplot parse this. I know I can change the underlying data and use label_parsed but would like to have the ability to ake an easily generalizable functions that others could use. This also allows one to keep the data as is (including correct factor levels) and just swap the labels. Otherwise you need to mutate the underlying data, and then add the correct factor levels so ordering is done properly.

After reading http://ggplot2.tidyverse.org/reference/labeller.html here's what I've tried.

library(ggplot2)

## can be used with label_parsed but order not retained
mtcars$mpg2 <- ifelse(mtcars$mpg > 20, 'beta', 'alpha')
## can be used with label_parsed and retains levels (but this is 2 steps)
mtcars$mpg3 <- factor(mtcars$mpg2, levels = c('beta', 'alpha'))

ggplot(mtcars, aes(mpg, disp)) +
    geom_point() +
    facet_grid(mpg3 ~ mpg2, 
        labeller = label_parsed
    )

## attempt #1 at a function
label_as_notation <- function(x, ...){
    parse(text = paste('"X:" ~ ', x, '<=', ifelse(x == 0, 'omega', 'psi')))
}

ggplot(mtcars, aes(mpg, disp)) +
    geom_point() +
    facet_grid( ~ am, 
        labeller = labeller(am = label_as_notation)
    )

enter image description here

So I wonder what does label_parsed do?

> label_parsed(1:3)
[[1]]
[[1]][[1]]
expression(1)


[[2]]
[[2]][[1]]
expression(2)


[[3]]
[[3]][[1]]
expression(3)

A list of lists of expressions. So I tried:

label_as_notation2 <- function(x, ...){

    y <- unlist(x)

    lapply(x, function(y) { 
        lapply(y, function(z) {
            parse(text = paste('"X:" ~ ', z, '<=', ifelse(z == 0, 'omega', 'psi')))
        })
    })
}

ggplot(mtcars, aes(mpg, disp)) +
    geom_point() +
    facet_grid( ~ am, 
        labeller = labeller(am = label_as_notation2)
    )

enter image description here

A similar think happens if I make label_parsed into a function:

ggplot(mtcars, aes(mpg, disp)) +
    geom_point() +
    facet_grid( ~ am, 
        labeller = labeller(am = function(x) label_parsed(x))
    )

enter image description here

So I guess it's not surprising my second approach didn't work. I have tried as_labeller wrapped around functions that return character but that doesn't parse.

How can I make a generalizable labeller that can switch labels with math notion on the fly so that they get parsed correctly by ggplot2?

Henrik
  • 65,555
  • 14
  • 143
  • 159
Tyler Rinker
  • 108,132
  • 65
  • 322
  • 519
  • Will `bquote` function with `plotmath` (grDevices) meet your needs? – Sixiang.Hu Mar 17 '18 at 17:05
  • this kinda works `label_as_notation <- function(x, ...) {list(lapply(unlist(x), function(X) parse(text = paste('"X:" ~ ', X, '<=', ifelse(x == 0, 'omega', 'psi')))))}; ggplot(mtcars, aes(mpg, disp)) + geom_point() + facet_grid( ~ am, labeller = label_as_notation)` – rawr Mar 17 '18 at 17:14
  • @rawr why kinda (other than not carrying the `X` to both spots)? – Tyler Rinker Mar 17 '18 at 17:33
  • I probably do not understand your question with my limited knowledge. may I kindly ask why you say that the data frame has to be mutated for label_parsed? With reference to https://stackoverflow.com/questions/34241890/ggplot-renaming-facet-labels-in-facet-wrap, one could simply create the factor within the `facet()` call : `...+ facet_wrap(~ factor(Species, levels = c('setosa', 'versicolor', 'virginica'), labels = c('setosa', 'versicolor', 'NULL^14*C~Amino~Acids')), labeller=label_parsed)` => no data frame mutation... ? – tjebo Mar 18 '18 at 19:34
  • 2
    @Tjebo I'm not looking for this for myself but to package it up that makes it easy for others to use. It seems to me that wanting to (1) alter labels & (2) parsing them should be an easy call to a parser function. Your approach, like alering the underying data requires a larger technical lift that I don't want to assume of my user. – Tyler Rinker Mar 19 '18 at 03:36

0 Answers0