Automatic adjustment of margins in horizontal bar chart

Max C picture Max C · May 8, 2012 · Viewed 10.4k times · Source

I need to produce a series of horizontal grouped bar charts. The barplot function does not automatically adjust the margins of the plot, therefore the text gets cut off.

  graphics.off()      # close graphics windows
   test <- matrix(c(55,65,30, 40,70,55,75,6,49,45,34,20), 
                  nrow =3 , 
               ncol=4, 
               byrow=TRUE,
               dimnames = list(c("Subgroup 1", "Subgroup 2", "Subgroup 3"),
                               c(
                                 "Category 1 Long text",
                                 "Category 2 very Long text",
                                 "Category 3 short text",
                                 "Category 4 very short text"
                                 )))
  barplot(test, 
       las=2,
       beside = TRUE,
       legend=T,
       horiz=T)

enter image description here

I can't find an option to automatically move the plot further to the right, the way R dotchart function does it ( (barchart procedure in SAS adjusts the margins automatically as well). Obviously, I can always adjust the margins manually using par function.

  par(mar=c(5.1, 13 ,4.1 ,2.1))

will move the plot to the right

enter image description here

Is there an option to move the plot to the right (i.e. adjust the margins) automatically depending on the length of the text?

I can think of 2 related appproaches to do it programmatically: 1) Calculate the length of the longest text string and accordingly adjust the left margin 2) Create a dotchart plot for the data, somehow capture the margins and use the same margins in bar chart.

Is there an easier way to do it? Thanks!

Answer

thelatemail picture thelatemail · May 8, 2012

I think your first idea is probably the most appropriate. Something like this seems to work okay and requires not much stuffing about.

ylabels <-  c(  "1oooooooooooo",
            "2",
            "3",
            "4"
)

test <- matrix(c(55,65,30, 40,70,55,75,6,49,45,34,20), 
                  nrow =3 , 
               ncol=4, 
               byrow=TRUE,
               dimnames = list(c("Subgroup 1", "Subgroup 2", "Subgroup 3"),
                               ylabels))

# adjust to the maximum of either the default 
# or a figure based on the maximum length
par(mar=c(5.1, max(4.1,max(nchar(ylabels))/1.8) ,4.1 ,2.1))

barplot(test, 
       las=2,
       beside = TRUE,
       legend=T,
       horiz=T)

After inspecting dotchart, a more generalisable solution may also be to use:

linch <-  max(strwidth(ylabels, "inch")+0.4, na.rm = TRUE)
par(mai=c(1.02,linch,0.82,0.42))