Skip to content
Back to formatted view

Raw Message

Message-ID: <alpine.DEB.2.00.0904301155360.20675@taxa.psych.umn.edu>
Date: 2009-04-30T18:01:58Z
From: Mike Miller
Subject: font size relative to graphic
In-Reply-To: <8685237E-0797-4AC3-BE1C-820892E064BB@comcast.net>

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