preventing centering multilayered caption in ggplo

2019-06-23 21:48发布

This is part-2 to my previous question (getting constant text size while using atop function in r).

Now the issue relates to how I can prevent plotmath from centering the text to avoid the extra spacing (highlighted here in yellow). I want everything aligned to the right side of the plot.

(Unfortunately, I can't replace substitute with expression if that's what your suggestion is going to be.)

Any suggestions?

library(ggplot2)

ggplot(iris, aes(Species, Sepal.Length)) +
  geom_boxplot()  +
  labs(caption = substitute(atop(
    atop(
      displaystyle("layer1 is small"),
      displaystyle("layer2 is a bit longer")
    ),
    "layer3 is super-duper longgggggggg"
  )))

enter image description here

2条回答
SAY GOODBYE
2楼-- · 2019-06-23 22:14

easiest might be to add text grobs row by row in a gtable,

gtable_add_caption <- function(p, cap, g = ggplotGrob(p), 
                               hjust=1, x=unit(1,"npc"), pad = unit(c(2,2),"mm"),
                               ...){

  for(ii in seq_along(cap)){
    line <- tryCatch(parse(text = cap[ii]), error = function(e) cap[ii])
    tg <- textGrob(line, x = x - pad[1], hjust = hjust, gp=gpar(...))
    hg <- grobHeight(tg) 
    g <- gtable_add_rows(g, hg + pad[2])
    g <- gtable_add_grob(g, tg, t = nrow(g), l=1, r=ncol(g))
  }

  g
}

p <- ggplot()
ggplot(iris, aes(Species, Sepal.Length)) +
  geom_boxplot() ->p
g <- gtable_add_caption(p, c("first line", "integral(frac(1,x-1)*dx,alpha,beta)", "thirdddddddddddddddddd line"))
grid.newpage()
grid.draw(g)
查看更多
家丑人穷心不美
3楼-- · 2019-06-23 22:18

Let's start with good news. Here's a function that adds enough leading spaces to from as to be as long as the longest element from the list to:

push <- function(from, to)
  sprintf(paste("%", max(nchar(from), max(nchar(to))), "s"), from)

Next we have three layers, which also may use substitute (as I understand, in your case only the first one uses it).

l1 <- substitute("layer1 is small")
l2 <- "layer2 is a bit longer"
l3 <- "layer3 is super-duper longgggggggg"

Now the bad news is that push achieves the desired effect only with mono fonts, which is not the default family in ggplot2. There are multiple question on SO regarding fonts, so perhaps you may import some other mono font, if you prefer.

ggplot(iris, aes(Species, Sepal.Length)) +
  geom_boxplot()  +
  labs(caption = substitute(atop(atop(textstyle(l1), textstyle(l2)), textstyle(l3)), 
                            list(l1 = push(l1, list(l2 ,l3)),
                                 l2 = push(l2, list(l1, l3)), 
                                 l3 = push(l3, list(l2, l3))))) +
  theme(plot.caption = element_text(family = "mono"))

enter image description here

查看更多
登录 后发表回答