[R] Barplot coloring question

Marc Schwartz mschwartz at medanalytics.com
Sat Jul 27 01:36:45 CEST 2002

> I have snipped the original message text to conserve space, since my
reply is long.

The source of the problem that you are having in trying to get the
colors to cycle in the case where you only have one row in your matrix
(data2), is in the way that the rectangles are drawn in barplot(). The
way it is coded, it precludes cycling the colors when beside = FALSE and
there is only one vector of height values.

The only time that colors cycle is when beside = TRUE or when there is
more than one set of height values, such as a stacked bar.

In reviewing the source code (yet again for barplot, which I have done
previously for myself on another issue), an internal barplot() function
called xyrect() is used.

xyrect() calls the standard R function rect(), which actually draws the
colored rectangles in the configuration specified by the arguments to

The code snippet from barplot.default() calling (not defining) xyrect()

if (beside)
   xyrect(0, w.l, c(height), w.r, horizontal=horiz, col = col)
else {
    for (i in 1:NC) {
        xyrect(height[1:NR, i], w.l[i], height[-1, i], w.r[i],
horizontal=horiz, col = col)

When beside = TRUE, each of the arguments is passed as a vector in the
first call to xyrect(), thus normal R cycling occurs, including the

However, when beside = FALSE, note that the for loop passes arguments by
explicit indexing in the second call to xyrect().  The loop repeats for
each value in NC, which is the number of columns in the matrix.

Note that "col" is not indexed (ie. col[i] ) in the looped call, thus
only the first value for color is passed when NR = 1 (one vector of
height values) and no cycling through the color vector occurs.  

When NR > 1, cycling within the xyrect() call takes place and the color
vector is cycled to allow for the multi-color segments in a stacked bar

Hence, you are stuck in this particular case, unless you want to modify

By the way, if "col" was indexed as col[i] in the code, it would address
your problem, but it would now preclude color cycling in stacked bars as
"i" would increment with each matrix column and not within each bar

My guess is that the author of barplot allowed for color cycling in
stacked and grouped bars, but not in the case of a single set of
non-stacked bars.

You could feasibly modify the code for the special case when NR = 1,
such as you have in data2 to enable each bar to be a different color or
pairs of colors as specified by the color vector. You would have to set
up the code to properly configure the color vector or pass it explicitly
in barplot.  For data2, the explicit argument could be something like:

 "col = rep(c("orange", "yellow"), 3)" 

which would create a vector of:

[1] "orange" "yellow" "orange" "yellow" "orange" "yellow" 

Not sure if that is what you wanted to hear, but I think that may be
your only choice, unless others reading this have other ideas about how
to approach the issue.

The other alternative, would be as I had suggested earlier, which is to
use beside = TRUE for the special case where your number of rows = 1,
with the space arguments in a standard configuration and the data set up
with multiple rows per group and only one column per group. In the cases
where the number of rows > 1, then take the "beside = FALSE" approach.

I think you have it right for when the number of rows in your data is >1
using the reversed space argument values.  It seems to yield what you
are trying to achieve, which is paired groupings of grouped bars.

Hope that provides some direction. If I have missed anything else, let
me know.


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

More information about the R-help mailing list