Hello everybody, often I plot boxplots with different number of boxes (up to 200 boxes). I'd like to give every box a readable label on the x-axis. Therefore, I decrease the fontsize of the names and plot them vertical. But if you zoom into the plot (pdf) you will find an offset between the tickmark and the label - the label is shifted to the right. If you vary the box.count in the following example (without changing the fontsize) you will find every time this right shifted labels. (Finaly, for large box.counts the label will be shifted to the next right label!) Question 1: How can I avoid the right shift of the x-axis label? Question 2: Is it possible to scale the fontsize depending of the box.count (So that I can read every single label)? Thank's in advance - regards, Lutz #---------------------------- box.count<-150 data(ToothGrowth) DATA<-list(ToothGrowth$len) DATA<-rep(DATA,box.count) box.name<- rep('any text',box.count) pdf(file='boxplot_test.pdf',width=11,height=8) # So I can read every label using the pdf reader zooming functionality. par(cex.axis=.5) # make axis font smaller, par(las=3) # plot all axis label vertical b<-boxplot(DATA,plot=FALSE, names=box.name) bxp(b,show.names=T) graphics.off() #---------------------------- platform sparc-sun-solaris2.6 arch sparc os solaris2.6 system sparc, solaris2.6 status major 1 minor 4.1 year 2002 month 01 day 30 language R Lutz Thieme Product Engineering AMD - Saxony Manufacturing GmbH phone: + 49-351-277 - 4269 fax: + 49-351-277-9-4269 -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- r-help mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html Send "info", "help", or "[un]subscribe" (in the "body", not the subject !) To: r-help-request at stat.math.ethz.ch _._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._
Hi> often I plot boxplots with different number of boxes (up to 200 boxes). > I'd like to give every box a readable label on the x-axis. Therefore, I > decrease the fontsize of the names and plot them vertical. > But if you zoom into the plot (pdf) you will find an offset between the > tickmark and the label - the label is shifted to the right. > > If you vary the box.count in the following example (without changing > the fontsize) you will find every time this right shifted labels. > (Finaly, for large box.counts the label will be shifted to the next right > label!) > > Question 1: How can I avoid the right shift of the x-axis label? > Question 2: Is it possible to scale the fontsize depending of the box.count > (So that I can read every single label)?The problem here is with mtext(). A simpler demonstration of the problem is as follows ... plot(1:10) abline(v=1:10, col="grey") axis(3, at=1:10, las=3) axis(3, pos=9, at=1:10, las=3, cex.axis=.5) axis(3, pos=8, at=1:10, las=3, cex.axis=2) ... basically mtext() is using a hardcoded adjustment to position the text in some cases. It looks ok for the default text size, but gets it wrong if the text size is modified. (I will submit a bug report about this problem). The temporary hack solution requires using text() instead of mtext() to draw the axis labels. Here's one way to do it ... # Make sure that the text() output is not clipped par(xpd=NA) # Create the boxplot information b <- boxplot(list(rnorm(10), rnorm(10), rnorm(10), rnorm(10), rnorm(10), rnorm(10), rnorm(10), rnorm(10), rnorm(10), rnorm(10)), plot=FALSE) # Draw the boxplot # We control the y-axis scale so that we have some hope of # positioning the text() output later bp <- bxp(b, ylim=c(-4, 4), axes=FALSE) axis(2) box() # Draw the x-axis ticks axis(1, at=bp, labels=FALSE) # Draw the x-axis tick labels using trial-and-error to # get the value -4.7 text(bp, -4.7, letters[1:10], srt=90, adj=c(1, .5), cex=.5) .. The disadvantage is that it requires trial-and-error to position the labels. This is maybe not too much pain for a one-off boxplot, but may get tiresome if many boxplots are to be produced. Another approach which is not dependent on the y-axis scale is a bit more complicated, but for the brave of heart here goes ... # First split the page into two figure regions # The lower region is .5cm high for the axis we will draw # plus .5in high for the axis labels -- change this second # amount to allow for longer labels layout(matrix(c(1, 2), ncol=1), heights=c(1, lcm(.5 + 2.54/2))) # Prepare to draw the main boxplot # We make the bottom margin 0 so that the bottom of # the boxplot is flush with the top of the axis we will draw # We make the left and right margins something that we can # reproduce when we come to drawing the axis par(mai=c(0, 1, 1, .5)) # Create the boxplot information b <- boxplot(list(rnorm(10), rnorm(10), rnorm(10), rnorm(10), rnorm(10), rnorm(10), rnorm(10), rnorm(10), rnorm(10), rnorm(10)), plot=FALSE) # Draw the boxplot, but not any axes bp <- bxp(b, axes=FALSE) # Draw the default y axis axis(2) box() # Save the axis scales -- we want the x-axis scale for later savedusr <- par("usr") # Prepare to draw the axis # We make the top margin 0 so that the top of the axis # will be flush with the bottom of the boxplot # We replicate the left and right margins from the boxplot # The bottom margin is .5in -- the amount of room we allowed # for in the layout # We set xpd=NA so that the text drawn for the axis tick # labels will not get clipped par(mai=c(.5, 1, 0, .5), xpd=NA) # Start a new plot -- the text() function draws in the # "data region" of a plot, so we will draw the axis as a # complete plot plot.new() # Set up the scales on the new plot # We replicate the x-axis scale from the boxplot # The choice of y-axis scale is arbitrary plot.window(savedusr[1:2], c(1, 10), xaxs="i", yaxs="i") # Draw the axis ticks -- note that this axis is drawn at # the very top of the new plot (pos=10) axis(1, at=bp, pos=10, labels=FALSE) # Draw the axis tick labels text(bp, 1, letters[1:10], srt=90, adj=c(1, .5), cex=.5) ... anyway, that's a couple of ideas :) Hope there's something useful in there somewhere. Paul -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- r-help mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html Send "info", "help", or "[un]subscribe" (in the "body", not the subject !) To: r-help-request at stat.math.ethz.ch _._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._
Hi> often I plot boxplots with different number of boxes (up to 200 boxes). > I'd like to give every box a readable label on the x-axis. Therefore, I > decrease the fontsize of the names and plot them vertical. > But if you zoom into the plot (pdf) you will find an offset between the > tickmark and the label - the label is shifted to the right. > > If you vary the box.count in the following example (without changing > the fontsize) you will find every time this right shifted labels. > (Finaly, for large box.counts the label will be shifted to the next right > label!) > > Question 1: How can I avoid the right shift of the x-axis label? > Question 2: Is it possible to scale the fontsize depending of the box.count > (So that I can read every single label)?... and here's yet another approach, this time using the grid package to draw the entire plot from scratch. Its a bit lengthy because I had to create functions to draw a basic boxplot, but it might provide a sufficient framework for you to build on. It is also specific to your problem (although with a few parameters it could be generalised further). Paul ## grid boxplot code library(grid) grid.bp <- function(stats, width, out) { grid.rect(y=unit(stats[2], "native"), height=unit(stats[3] - stats[2], "native"), width=width, just=c("centre", "bottom")) grid.rect(y=unit(stats[3], "native"), height=unit(stats[4] - stats[3], "native"), width=width, just=c("centre", "bottom")) grid.segments(x0=.5, x1=.5, y0=unit(stats[c(1, 4)], "native"), y1=unit(stats[c(2, 5)], "native"), gp=gpar(lty="dashed")) grid.segments(y0=unit(stats[c(1, 5)], "native"), y1=unit(stats[c(1, 5)], "native"), x0=unit(.5, "npc") - unit(2, "mm"), x1=unit(.5, "npc") + unit(2, "mm")) if (length(out) > 0) grid.points(x=unit(rep(.5, length(out)), "npc"), y=unit(out, "native")) } grid.bxp <- function(boxplot) { nbp <- ncol(boxplot$stats) scalevp <- dataViewport(xscale=c(0, 1), y=c(boxplot$stats, boxplot$out)) push.viewport(scalevp) grid.yaxis() grid.rect() push.viewport(viewport(layout=grid.layout(1, nbp))) for (i in 1:nbp) { push.viewport(viewport(layout.pos.col=i)) push.viewport(scalevp) grid.bp(boxplot$stats[,i], unit(.8, "npc"), boxplot$out[boxplot$group == i]) grid.lines(y=unit(c(0, -.5), "lines"), x=rep(.5, 2)) grid.text(boxplot$names[i], y=unit(-1, "lines"), rot=90, just=c("right", "centre"), gp=gpar(fontsize=6)) grid.text(boxplot$names[i], y=unit(-2, "lines"), rot=90, just=c("right", "centre")) grid.text(boxplot$names[i], y=unit(-3, "lines"), rot=90, just=c("right", "centre"), gp=gpar(fontsize=18)) pop.viewport(2) } } b <- boxplot(list(rnorm(10), rnorm(10), rnorm(10), rnorm(10), rnorm(10), rnorm(10), rnorm(10), rnorm(10), rnorm(10), rnorm(10)), plot=FALSE) push.viewport(plotViewport(c(5, 4, 4, 2))) grid.bxp(b) pop.viewport() -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- r-help mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html Send "info", "help", or "[un]subscribe" (in the "body", not the subject !) To: r-help-request at stat.math.ethz.ch _._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._