[R] font size relative to graphic

Mike Miller mbmiller+l at gmail.com
Thu Apr 30 20:01:58 CEST 2009


In my particular situation, the trick was to figure out what worked for 
one set of bars, then determine how bar widths changed when various 
graphing parameters changed.  Then I used that information to decide on a 
"cex" (character expansion) multiplier that worked perfectly for every 
example I produced (this was called "bar_cex" in my R code, which is shown 
below).

There are a couple of neat things about the horizontal bar plot that 
everyone can use in choosing their cex.  First, when there are n sets of m 
bars per set, then the vertical distance from the lower side of the bottom 
bar to the top side of the top bar is divided into n*(m+1)-1 equal-height 
regions and every bar width (vertical distance for horizontal bars, used 
to determine character height) is 1/(n*(m+1)-1) times that total vertical 
distance.  So just find the right cex for one set of bars, say n=3, m=2, 
so that n*(m+1)-1 = 7, then use bar_cex = cex*7/(n*(m+1)-1) for other 
values of n and m.

In my situation, using pdf with letter paper, height=11, width=8.5, I also 
used a variable number of inches empty on the top of the page.  I called 
that number of inches "top_inches".  I then figured out the correct cex 
when the plot height was at a max of .78 and used (.78-top_inches/11) to 
figure cex for other values of top_inches.  After a little arithmetic I 
came up with the equation appended below for bar_cex.  It works for me, 
but it won't work for other people.  This probably will work for other 
situations:

bar_cex <- C/(n*(m+1)-1)

Where an appropriate value of C that works for one collection of 
horizontal bars (n sets of m bars per set) will work for other sets of 
bars.

Mike


bar_cex <- (51/(n*(m+1)-1))*(.78-top_inches/11)


# generate the horizontal bar plot and store values for later use
x.bar.plot <- barplot(as.matrix(x), col=rep(rev(bar.colors[1:m]),n), horiz=TRUE,
                       beside=TRUE, xlim=c(0,100), main=bar.main.title,
                       xlab=bar.x.label, las=1, cex.names=min( c(1, 16/L) ),
                       legend=labels.legend)
# add numbers to bars
text(as.matrix(x), x.bar.plot-.1, as.character(as.matrix(round(x))), pos=2,
      offset=0.1, col="black", cex=bar_cex)

If I don't subtract .1 from x.bar.plot, the text is positioned too high 
(vertically) on the horizontal bar.



On Fri, 24 Apr 2009, David Winsemius wrote:

>
> On Apr 24, 2009, at 4:10 PM, Mike Miller wrote:
>
>> On Fri, 24 Apr 2009, David Winsemius wrote:
>> 
>>> On Apr 24, 2009, at 3:14 PM, Mike Miller wrote:
>>> 
>>>> I am printing numbers onto horizontal bars in a bar plots, but I am 
>>>> finding it difficult to make the number always the right size.  If there 
>>>> are more bars, the bars get narrower and the font is too big.  I also 
>>>> find that if I change the size of the graph, the bars will get wider or 
>>>> narrower and the font stays about the same size.  The result depends on 
>>>> whether I view the graph in X11 or in postscript.
>>>> Is there a way to specify font size relative to bar width, or at least 
>>>> specify font size relative to graph coordinates?
>>>> Here's a bit of what I've been doing:
>>>> x.bar.plot <- barplot(as.matrix(x), horiz=TRUE, beside=TRUE, 
>>>> xlim=c(0,100), xlab="Score", las=1)
>>>> text(as.matrix(x), x.bar.plot-.07, as.character(as.matrix(round(x))), 
>>>> pos=2, col="black")
>>>> The "-.07" is something I added to make the numbers align well with the 
>>>> bars under one condition, but it doesn't always help.
>>>> Any tips would be greatly appreciated.  Thanks in advance.
>>> 
>>> The values returned from the barplot function are the locations of the 
>>> bars. Why not call barplot, collect the values, and then use the length of 
>>> the result to determine your sizes and widths?
>> 
>> That is exactly the kind of thing I want to do, but I don't know how the 
>> font size can be specified so that it fits.  My bars are horizontal and 
>> yours (from code below) are vertical.  Your barplot output was called "mp" 
>> and mine was called "x.bar.plot" and here is what they looked like:
>> 
>>> mp
>>    [,1] [,2] [,3] [,4] [,5]
>> [1,]  1.5  6.5 11.5 16.5 21.5
>> [2,]  2.5  7.5 12.5 17.5 22.5
>> [3,]  3.5  8.5 13.5 18.5 23.5
>> [4,]  4.5  9.5 14.5 19.5 24.5
>> 
>>> x.bar.plot
>>    [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
>> [1,]  1.5  4.5  7.5 10.5 13.5 16.5 19.5 22.5 25.5  28.5  31.5  34.5
>> [2,]  2.5  5.5  8.5 11.5 14.5 17.5 20.5 23.5 26.5  29.5  32.5  35.5
>> 
>> They are pretty similar numbers.  It seems that [1,1] element is always 1.5 
>> and consecutive elements in the same column differ by 1.0, but in the rows 
>> we see something different: mine are 3.0 apart and yours are 5.0 apart.  So 
>> what does this tell me?  I think fonts are specified in points which 
>> correspond to 1/72 inches, while bars are specified in coordinates that are 
>> independent of inches.  So I need to know how coordinates correspond to 
>> inches before I can get this fixed.
>
> They do not correspond to inches, but the the numeric scale of the values. 
> Here is your plot with the numbers moved so they are to the right of the bar 
> ends:
>
> txt <- "1.5  4.5  7.5 10.5 13.5 16.5 19.5 22.5 25.5  28.5  31.5  34.5
> 2.5  5.5  8.5 11.5 14.5 17.5 20.5 23.5 26.5  29.5  32.5  35.5"
> x <- read.table(textConnection(txt), header=FALSE)
>
> x.bar.plot <- barplot(as.matrix(x), horiz=TRUE, beside=TRUE, xlim=c(0,100), 
> xlab="Score", las=1)
> text(as.matrix(x+6), x.bar.plot-.07, as.character(as.matrix(round(x))), 
> pos=2, col="black")
>
> # the rounding is what makes the dissimilar bars labeled with the same 
> numbers, ... yecch.
>
> Haven't figured out what the requirements on sizing really are;  but here is 
> an example you might play with:
>
> text(as.matrix(x+6), x.bar.plot-.07, as.character(as.matrix(round(x))), 
> pos=2, col="black",
>   cex= 24/length(as.matrix(x)))
>
>
> David Winsemius, MD
> Heritage Laboratories
> West Hartford, CT




More information about the R-help mailing list