[R] Barplot coloring question

Marc Schwartz mschwartz at medanalytics.com
Mon Jul 29 22:17:30 CEST 2002


> -----Original Message-----
> Hi Marc,
> 
> Thanks for that very helpful explanation about barplot's innards.
Your
> suggestion works perfectly for NR = 1, so that problem is resolved. 

Glad to be of help.

> Now on
> to NR > 1. I am trying the following. I am trying to define a new
> function, mybarplot, in which the assumption is that the colors are
> presented as a matrix, so:
> 
> v <- c("red","yellow","green")
> 
> colormatrix <- cbind(v,v,v,v,v,v)

Here you might want to think about using something like:

colormatrix <- matrix(c(rep(v, 6)), ncol = 6)

This will give you more flexibility structuring this in a function that
you can create by passing a value in place of the "6" to allow for
varying numbers of columns, which could be derived from the dimensions
of your data object and for a varying number of colors stored in a
vector "v" that you pass to the function.

However, I am not yet sure that you need a 2 dimensional matrix for what
you are doing. If you are just using the same 3 colors for each cycle,
just use a vector of the three colors. They don't need to be repeated if
you are calling them inside a loop. This is what the original barplot()
is doing with the call to xyrect(), where the colors cycle in the bar
segments.

If you actually want each group of bars to have a different set of three
colors, then you would need a matrix, with a vector for each group.
 
> which gives:
> 
> > colormatrix
>      v        v        v        v        v        v
> [1,] "red"    "red"    "red"    "red"    "red"    "red"
> [2,] "yellow" "yellow" "yellow" "yellow" "yellow" "yellow"
> [3,] "green"  "green"  "green"  "green"  "green"  "green"
> 
> Now, the crucial change to the barplot code is that I add another
> for-loop:
> 
>   if (beside)
>             xyrect(0, w.l, c(height), w.r, horizontal = horiz,
>                 col = col)
>         else {
>             for (i in 1:NC) {
>                      for (j in 1:NR) { # new loop added
>                        col = col[,i]
>                        xyrect(height[1:NR, i], w.l[i], height[-1, i],
>                             w.r[i], horizontal = horiz, col = col[j])
>                      }
>             }
>         }
> 
> The reasoning here is that if beside = FALSE, and I have a data
> structure data3 like this:
> 
>    A  A  B  B  C  C
> 1  5 10 15 20 70 90
> 2 20 15 24 56 34 70
> 3 40 54 23 67 12 78
> 
> then, for each column of data3, cycle through the colors "red",
"yellow",
> and "green". This means that for each column in data3, I successively
do
> the following for the j (= 3) rows of data3: get the color-vector
> corresponding to the current column from data3 (I want to enforce this
> correspondence for now so that I can have alternating triplets of
colors
> if I want). That is, I get the three colors in a vector (col =
col[,i]),
> and then go through these colors in turn, i.e., get the jth color each
> time (this is the intended purpose of the inner for loop).
> 
> So, the call to mybarplot would be:
> 
> mybarplot(data3,
>         beside=FALSE,
>         col= colormatrix,
>         width = c(1,.55),
>         space = c(2.75,.25),
>         axes = F)
> 
> But this doesn't work; I get the message:
> 
> "Error in col[, i] : incorrect number of dimensions"
> 
> If you can easily see what's wrong here in my code, please do tell.
> Meanwhile I will keep trying to figure out what I'm missing.

The problem that you are having which results in the error message is
that after the first time through the inner loop, "col" is no longer a
matrix, it is a vector as you are "stepping" on it when you re-assign it
to col[,i] the first time. You lose the original value of the color
matrix.

Thus, the second time through the loop, you get the error message, since
you are trying to index "col" as a matrix when it is now one dimensional
and not two. 

Change the code to:

mycol = col[,i]
xyrect(height[1:NR, i], w.l[i], height[-1, i], w.r[i], horizontal =
horiz, col = mycol[j])

Once you correct this, you will note that all of your bars end up green.
Now you can see the result of a second problem, which is that you are
passing by explicit index, each of the three colors in your vector
during the "j" loop.  For each iteration through the "j" loop, xyrect()
is drawing all of the bar segments for all 6 bars.  The way you have it
now, three times.  Once with red, once with yellow and then finally with
green as "j" increments, so they all end up green. 

Now make the final change to the code, removing the subscript for mycol:

mycol = col[,i]
xyrect(height[1:NR, i], w.l[i], height[-1, i], w.r[i], horizontal =
horiz, col = mycol)

Again, keep in mind that all of the bar segments for all of the bars are
being drawn inside the *single* call to xyrect(), thus you need to pass
the full vector of three colors to xyrect() at once if you want each
segment to be a different color.

The question this whole process now raises is why the inner loop?
 
One other error avoiding thought, is that when doing an assignment
outside of a function argument, use the "<-" instead of "=".  It avoids
many problems which have been discussed here of late.  If you get into
the habit of using "=", you may accidentally use it when performing an
equality comparison using "==".  Thus, as the result of a typo, you
perform an assignment when you really want to do a comparison (or vice
versa).

I am still a little confused as to how you want the colors structured.
That is do you want each bar to contain the three colors, one for each
segment, or do you want each of the three pairs of bars to be colored
differently?

If the former, which I think is correct, then the original barplot()
code will work fine.

For example, use:

barplot(data3, beside = FALSE, col = c("red", "yellow", "green"), width
= c(1, .55), space = c(2.75, .25), axes = FALSE)

Let me know on that.

> A propos, how do I find out how exactly "xyrect" is defined?

If you have downloaded the source code from CRAN, look for the file
barplot.r in the archive file.  You can then review the full code for
the function.

If you have not, an alternative would be to type in:

"barplot.default"

without the quotes at the prompt. That will display the R code for the
function.
 
> Many thanks again for spending so much time on this. I'm learning a
lot...

You are welcome.  HTH.

Marc


-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
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