To all,
Recently I created a version of barplot() to include some new features
as follows:
1. Plot confidence intervals for each bar: The user can pass lower
(ci.l) and upper (ci.u) bounds in the same vector/matrix format as
"height". The CI boundary lines will vary in width per bar, if a
varying "width" argument is specified. CI line width, type and color
can
be defined. Defaults to 1, "solid" and black, respectively. Works
with
horizontal or vertical plot. Will work with beside = TRUE. Will not work
if stacked bar plot results at this time. Argument plot.ci = c("TRUE",
"FALSE") defines whether these are drawn.
2. Color plot region separately from the background area, if desired.
Argument "prcol" defaults to NULL.
3. Draw "height" axis grid lines *behind* the bars. Grid line width,
type and color can be specified. Defaults to 1, "dotted" and black
respectively. Argument plot.grid = c("TRUE", "FALSE")
defines if the
grid is plotted.
I have made these modifications with the intent to not "break" any
existing code, so that identical calls to this version should work the
same as the current implementation.
The current full function argument list is as follows:
barplot2 <- function(height, ...) UseMethod("barplot2")
barplot2.default <-
function(height, width = 1, space = NULL, names.arg = NULL,
legend.text = NULL, beside = FALSE, horiz = FALSE,
density = NULL, angle = 45,
col = heat.colors(NR), prcol = NULL, border = par("fg"),
main = NULL, sub = NULL, xlab = NULL, ylab = NULL,
xlim = NULL, ylim = NULL, xpd = TRUE, log = "",
axes = TRUE, axisnames = TRUE,
cex.axis = par("cex.axis"), cex.names =
par("cex.axis"),
inside = TRUE, plot = TRUE,
plot.ci = FALSE, ci.l = NULL, ci.u = NULL,
ci.color = "black", ci.lty = "solid", ci.lwd = 1,
plot.grid = FALSE, grid.inc = 5,
grid.lty = "dotted", grid.lwd = 1, grid.col = "black",
...)
In late August, there was a post from Rengie Chan with a query on using
log axis scaling with barplot(), which is presently precluded as coded
as per my reply to his post. I also noted that Paul Murrell has a note
about this on his to-do page at:
http://www.stat.auckland.ac.nz/~paul/R/graphicstodos.html
I have spent some time over the past couple of weeks or so (thinking
that this was going to be easier than it turned out to be) working on
this as time has permitted.
I now have barplot2() working with both x and/or y axis log scaling, for
single bars, multiple bars ("beside = TRUE") and for stacked bars.
Some of the key issues are of course preventing log(<=0) related errors
in the axis scaling, which I have done and incorporating the other
features that I have added above to be compatible with log scaling.
These include adjusting the par("usr") values as well as the bar
baseline values when stacked for log scaling and so forth. Also, the
"hatch" type bar shading does not work with a log scale, so an error
check is included to catch this.
I have attached the R code for this version, called barplot2(), for the
time being. I make this code available to R-Core if so desired, and to
the community at large. If anyone finds any bugs, let me know.
The areas that I am still a bit unsure of (and open to criticism on) are
as follows:
1. When using log scaling, I have arbitrarily set the lower limit of the
"height" related axis to 0.9 * min(height), to enable some of the
smallest bar to actually be plotted. This figure is adjusted to include
0.9 * min(ci.l) when plotting CI's. This can be over-ridden by setting
either ylim or xlim explicitly of course. If anyone feels that this
should be different, let me know.
2. When plotting grid lines, I have resorted to using pretty() to define
the axis tick marks, labels and grid lines by default. This took some
time, after I noted posts to R-Help on the issues with par("xaxp") and
par("yaxp") when log scaling is used. I also noted Ross Ihaka's
sci.axis() function. I wrestled with trying to be consistent in the
behavior of the grid lines for both linear and log scaling and differing
approaches.
However, given that both barplot() and more significantly the axis() C
code in plot.c forces "lty = 0" as presently coded, I wanted to give
the
user the ability to visually "de-emphasize" the gridlines with
alternative line types, widths and colors. Thus I am using abline() with
intervals set by pretty(), with the user able to specify how many
intervals using "grid.inc", with a default of 5 as in pretty(). If
anyone has any better thoughts on how to approach this, I am open.
I was trying to figure out a way to call the C code in plot.c that
generates the default axis intervals (CreateAtVector), but would get
errors indicating that the function is not in the load table. This
would seem to be a cleaner approach at first glance, since it would
result in consistent default axis interval behavior when not plotting
grid lines. I am open to pointers or other thoughts on this.
Finally, there are two .NotYetUsed arguments in barplot().
First is "border", which defaults to par("fg"). I presume
that this is
simply meant to be the "border" argument to rect()? If so, I can make
that change easily.
Second is the "inside" argument. If I read the help file correctly,
this will draw a line between adjacent bars. However, I am unsure if
this is intended to be a "grouping" line that runs the full height or
width of the plotting region such that it divides a group of bars (ie.
beside = TRUE) or if it is simply a heavier line between each bar. If
someone can clarify this, I can work on this as well.
I appreciate any feedback from the group and hope that this work is of
value to users of barplot().
Best regards,
Marc Schwartz