preventing centering multilayered caption in ggplot2









up vote
2
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
2
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
2
down vote

favorite









up vote
2
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,304213




1,304213







  • 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
1
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










    New contributor




    user10630867 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.

















      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',
      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
      1
      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



        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



          accepted







          up vote
          1
          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

          26.4k75877




          26.4k75877






















              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










              New contributor




              user10630867 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
              Check out our Code of Conduct.





















                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










                New contributor




                user10630867 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                Check out our Code of Conduct.



















                  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










                  New contributor




                  user10630867 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                  Check out our Code of Conduct.









                  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










                  New contributor




                  user10630867 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                  Check out our Code of Conduct.









                  share|improve this answer



                  share|improve this answer








                  edited Nov 10 at 21:56





















                  New contributor




                  user10630867 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                  Check out our Code of Conduct.









                  answered Nov 10 at 21:39









                  user10630867

                  112




                  112




                  New contributor




                  user10630867 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                  Check out our Code of Conduct.





                  New contributor





                  user10630867 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                  Check out our Code of Conduct.






                  user10630867 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                  Check out our Code of Conduct.



























                       

                      draft saved


                      draft discarded















































                       


                      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







                      Popular posts from this blog

                      Top Tejano songwriter Luis Silva dead of heart attack at 64

                      政党

                      天津地下鉄3号線