preventing centering multilayered caption in ggplot2











up vote
4
down vote

favorite












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










share|improve this question




















  • 1




    There are already few related question (see plotmath alignment). E.g., would manually adding spaces as in stackoverflow.com/questions/35781950/… would be acceptable? Rather than actually manually trying different numbers of spaces it could be somewhat automatized.
    – Julius Vainora
    Nov 10 at 14:58












  • Yeah, but the problem is that all of them use expression to create the caption, while I am using substitute. The solutions provided of course don't work well with substitute. (In case you are wondering why the obsession with substitute, this is the kind of context where I am using it- github.com/IndrajeetPatil/ggstatsplot/blob/…)
    – Indrajeet Patil
    Nov 10 at 15:02








  • 1




    So I guess the problem is that the text is not of fixed length. Why don't you update your example a little where manually adding, say, 30 spaces doesn't fix the problem? Then I'll give it a try.
    – Julius Vainora
    Nov 10 at 15:11










  • The text in layer 2 and layer 3 are of fixed length, so that will be easy to fix. It's the layer 1 that will vary because the user can choose to enter caption of any length they want.
    – Indrajeet Patil
    Nov 10 at 18:54















up vote
4
down vote

favorite












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










share|improve this question




















  • 1




    There are already few related question (see plotmath alignment). E.g., would manually adding spaces as in stackoverflow.com/questions/35781950/… would be acceptable? Rather than actually manually trying different numbers of spaces it could be somewhat automatized.
    – Julius Vainora
    Nov 10 at 14:58












  • Yeah, but the problem is that all of them use expression to create the caption, while I am using substitute. The solutions provided of course don't work well with substitute. (In case you are wondering why the obsession with substitute, this is the kind of context where I am using it- github.com/IndrajeetPatil/ggstatsplot/blob/…)
    – Indrajeet Patil
    Nov 10 at 15:02








  • 1




    So I guess the problem is that the text is not of fixed length. Why don't you update your example a little where manually adding, say, 30 spaces doesn't fix the problem? Then I'll give it a try.
    – Julius Vainora
    Nov 10 at 15:11










  • The text in layer 2 and layer 3 are of fixed length, so that will be easy to fix. It's the layer 1 that will vary because the user can choose to enter caption of any length they want.
    – Indrajeet Patil
    Nov 10 at 18:54













up vote
4
down vote

favorite









up vote
4
down vote

favorite











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










share|improve this question















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







r ggplot2 plotmath






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 10 at 14:31

























asked Nov 10 at 14:07









Indrajeet Patil

1,442213




1,442213








  • 1




    There are already few related question (see plotmath alignment). E.g., would manually adding spaces as in stackoverflow.com/questions/35781950/… would be acceptable? Rather than actually manually trying different numbers of spaces it could be somewhat automatized.
    – Julius Vainora
    Nov 10 at 14:58












  • Yeah, but the problem is that all of them use expression to create the caption, while I am using substitute. The solutions provided of course don't work well with substitute. (In case you are wondering why the obsession with substitute, this is the kind of context where I am using it- github.com/IndrajeetPatil/ggstatsplot/blob/…)
    – Indrajeet Patil
    Nov 10 at 15:02








  • 1




    So I guess the problem is that the text is not of fixed length. Why don't you update your example a little where manually adding, say, 30 spaces doesn't fix the problem? Then I'll give it a try.
    – Julius Vainora
    Nov 10 at 15:11










  • The text in layer 2 and layer 3 are of fixed length, so that will be easy to fix. It's the layer 1 that will vary because the user can choose to enter caption of any length they want.
    – Indrajeet Patil
    Nov 10 at 18:54














  • 1




    There are already few related question (see plotmath alignment). E.g., would manually adding spaces as in stackoverflow.com/questions/35781950/… would be acceptable? Rather than actually manually trying different numbers of spaces it could be somewhat automatized.
    – Julius Vainora
    Nov 10 at 14:58












  • Yeah, but the problem is that all of them use expression to create the caption, while I am using substitute. The solutions provided of course don't work well with substitute. (In case you are wondering why the obsession with substitute, this is the kind of context where I am using it- github.com/IndrajeetPatil/ggstatsplot/blob/…)
    – Indrajeet Patil
    Nov 10 at 15:02








  • 1




    So I guess the problem is that the text is not of fixed length. Why don't you update your example a little where manually adding, say, 30 spaces doesn't fix the problem? Then I'll give it a try.
    – Julius Vainora
    Nov 10 at 15:11










  • The text in layer 2 and layer 3 are of fixed length, so that will be easy to fix. It's the layer 1 that will vary because the user can choose to enter caption of any length they want.
    – Indrajeet Patil
    Nov 10 at 18:54








1




1




There are already few related question (see plotmath alignment). E.g., would manually adding spaces as in stackoverflow.com/questions/35781950/… would be acceptable? Rather than actually manually trying different numbers of spaces it could be somewhat automatized.
– Julius Vainora
Nov 10 at 14:58






There are already few related question (see plotmath alignment). E.g., would manually adding spaces as in stackoverflow.com/questions/35781950/… would be acceptable? Rather than actually manually trying different numbers of spaces it could be somewhat automatized.
– Julius Vainora
Nov 10 at 14:58














Yeah, but the problem is that all of them use expression to create the caption, while I am using substitute. The solutions provided of course don't work well with substitute. (In case you are wondering why the obsession with substitute, this is the kind of context where I am using it- github.com/IndrajeetPatil/ggstatsplot/blob/…)
– Indrajeet Patil
Nov 10 at 15:02






Yeah, but the problem is that all of them use expression to create the caption, while I am using substitute. The solutions provided of course don't work well with substitute. (In case you are wondering why the obsession with substitute, this is the kind of context where I am using it- github.com/IndrajeetPatil/ggstatsplot/blob/…)
– Indrajeet Patil
Nov 10 at 15:02






1




1




So I guess the problem is that the text is not of fixed length. Why don't you update your example a little where manually adding, say, 30 spaces doesn't fix the problem? Then I'll give it a try.
– Julius Vainora
Nov 10 at 15:11




So I guess the problem is that the text is not of fixed length. Why don't you update your example a little where manually adding, say, 30 spaces doesn't fix the problem? Then I'll give it a try.
– Julius Vainora
Nov 10 at 15:11












The text in layer 2 and layer 3 are of fixed length, so that will be easy to fix. It's the layer 1 that will vary because the user can choose to enter caption of any length they want.
– Indrajeet Patil
Nov 10 at 18:54




The text in layer 2 and layer 3 are of fixed length, so that will be easy to fix. It's the layer 1 that will vary because the user can choose to enter caption of any length they want.
– Indrajeet Patil
Nov 10 at 18:54












2 Answers
2






active

oldest

votes

















up vote
2
down vote



accepted










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






share|improve this answer




























    up vote
    1
    down vote













    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)





    share|improve this answer























      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53239765%2fpreventing-centering-multilayered-caption-in-ggplot2%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes








      up vote
      2
      down vote



      accepted










      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






      share|improve this answer

























        up vote
        2
        down vote



        accepted










        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






        share|improve this answer























          up vote
          2
          down vote



          accepted







          up vote
          2
          down vote



          accepted






          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






          share|improve this answer












          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







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 10 at 20:00









          Julius Vainora

          30.7k75878




          30.7k75878
























              up vote
              1
              down vote













              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)





              share|improve this answer



























                up vote
                1
                down vote













                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)





                share|improve this answer

























                  up vote
                  1
                  down vote










                  up vote
                  1
                  down vote









                  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)





                  share|improve this answer














                  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)






                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Nov 10 at 21:56

























                  answered Nov 10 at 21:39









                  user10630867

                  262




                  262






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.





                      Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                      Please pay close attention to the following guidance:


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53239765%2fpreventing-centering-multilayered-caption-in-ggplot2%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      這個網誌中的熱門文章

                      Tangent Lines Diagram Along Smooth Curve

                      Yusuf al-Mu'taman ibn Hud

                      Zucchini