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