Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

parsed labels along one facet axis, unparsed labels along the other

Tags:

r

ggplot2

facet

I'm trying to find a convenient solution to a scenario where I have multi-line, plain-text labels for one faceting dimension and plotmath-style math expressions for the other faceting dimensions. The various solutions to multi-line strip labels (such as here) are a bit clunky for my case; I have factor labels in snake_case and want to be able to convert them all to multiline versions programmatically without descending into substitute(bquote(parse(...)) hell (although solutions along those lines would also be accepted).

The direction I went was to (try to) write a custom labeller that would apply label_parsed() or leave the labels alone depending on whether they contained newlines or not. I can't seem to get quite the right syntax for the parsed stuff. The current structure of the multi-line, unparsed stuff is

List of 1
 $ : chr [1:4] "peak\ntime" "peak\nvirulence" "equilibrium\nvirulence" "relative\npeak"

which works, but the parsed stuff is

List of 3
 $ :List of 1
  ..$ :  expression(beta)
 $ :List of 1
  ..$ :  expression(gamma)
 $ :List of 1
  ..$ :  expression(x[1])

which doesn't. Applying unlist(r) and unlist(r,recursive=FALSE) to this structure both give error messages ...

The result (shown below) is that all three of the parsed labels get stacked up in the first column ...

?label_parsed says

The return value must be a rectangular list where each 'row' characterises a single facet. The list elements can be either character vectors or lists of plotmath expressions. When multiple elements are returned, they get displayed on their own new lines (i.e., each facet gets a multi-line strip of labels).

Setup: load package, define old and new labels

library(ggplot2); theme_set(theme_bw())
orig_sum_labs <- c("peak_time","peak_vir","eq_vir","rel_peak")
new_sum_labs <- c("peak time","peak virulence","equilibrium virulence",
                  "relative peak")
fake <- data.frame(f1=rep(orig_sum_labs,each=12),
                   f2=factor(rep(1:3,16),levels=1:3,
                             labels=c("beta","gamma","x[1]")),
                   x=rep(1:4,12),y=rep(1:4,12))

Put newlines into labels:

nn <- gsub(" ","\n",new_sum_labs)
fake$f1 <- factor(fake$f1,levels=orig_sum_labs,labels=nn)

My labeller function:

L <- function(labels,multi_line=TRUE) {
    r <- if (all(grepl("\n",labels[[1]]))) {
        list(as.character(labels[[1]]))
    } else {
        label_parsed(labels[[1]],multi_line=multi_line)
    }
    ## browser()
    return(r)
}
class(L) <- "labeller"

Try it out:

ggplot(fake,aes(x,y))+geom_point()+
    facet_grid(f1~f2,labeller=L)

enter image description here

like image 269
Ben Bolker Avatar asked Oct 18 '22 09:10

Ben Bolker


People also ask

How to remove label from facet wrap?

To remove the label from facet plot, we need to use “strip. text. x” argument inside the theme() layer with argument 'element_blank()'.

What is meant by the term faceting in Ggplot?

Faceting is the process that split the chart window in several small parts (a grid), and display a similar chart in each section. Each section usually shows the same graph for a specific group of the dataset. The result is usually called small multiple.


1 Answers

Oops. It's a bit magical (and I would happily accept answers that explain clearly what's going on), but I managed to solve my problem. In my labeller function above,

label_parsed(labels[[1]],multi_line=multi_line)

doesn't work, but

label_parsed(labels,multi_line=multi_line)

works ...

enter image description here

like image 109
Ben Bolker Avatar answered Nov 01 '22 14:11

Ben Bolker