Stacked bar plot

I have a data-frame whose first column is the name of an item and the second column is the frequency of that item in the dataset.

 names            freq
1 tomato           7
2 potato           4
3 cabbage          5
4 sukuma-wiki      8
5 terere           20


I would like to have a stacked bar column that depicts the proportion of each entry on the chart. How do you handle coloring of the stacked bar when presented with over sixty entries? what is the easiest way to do this?

-

With 60 distinct categories, I feel you may have a hard time making that an effective graphic. You may want to consider a regular bar-chart that is sorted in ascending or descending order. Whether or not these are counts or percentages is up to you. Maybe something like this:

library(ggplot2)
df$names <- reorder(df$names, -df\$freq) #Reorders into ascending order
qplot(x = names, y = freq, data = df, geom = "bar") + coord_flip()


EDIT:

To make a stacked bar chart with ggplot, we set the x = 1 since we will have only one column. We will use the fill argument to add color:

qplot(x = factor(1), y = freq, data = df, geom = "bar", fill = names)


Also of interest: a stacked bar chart is pretty darn close to being a pie chart. You can transform the coordinate system of ggplot charts with + coord_polar(theta = "y") to make a pie chart from the stacked bar chart above.

-
 +1 for the use of qplot() but maybe it would be interesting to also show the other way (stacked) and the use of color. – chl♦ Dec 2 '10 at 7:39 +1 for the sorting – RockScience Dec 2 '10 at 7:48

I doubt you fill find a suitable range of distinct colours with so much categories. Anyway, here are some ideas:

1. For stacked barchart, you need barplot() with beside=FALSE (which is the default) -- this is in base R (@Chase's solution with ggplot2 is good too)
2. For generating a color ramp, you can use the RColorBrewer package; the example shown by @fRed can be reproduced with brewer.pal and any one of the diverging or sequential palettes. However, the number of colour is limited, so you will need to recycle them (e.g., every 6 items)

Here is an illustration:

library(RColorBrewer)
x <- sample(LETTERS[1:20], 100, replace=TRUE)
tab <- as.matrix(table(x))
my.col <- brewer.pal(6, "BrBG") # or brewer.pal(6, "Blues")
barplot(tab, col=my.col)


There is also the colorspace package, which has a nice accompagnying vignette about the design of good color schemes. Check also Ross Ihaka's course on Topic in Computational Data Analysis and Graphics.

Now, a better way to display such data is probably to use a so-called Cleveland dot plot, i.e.

dotchart(tab)

-
Cleveland plot, of course! – RockScience Dec 2 '10 at 7:51
I always seem to forget about dotcharts, even though everywhere you look Tufte talks about their superior data-ink ratio... I think this suggestion combined with the reordering of the data makes for an informative and easy to digest graph. For completeness sake, to change from bars to points in ggplot2 simply needs the geom = "point": qplot(x = names, y = freq, data = df, geom = "point") + coord_flip() – Chase Dec 2 '10 at 8:09
@Chase Thanks for this (I also appreciated that you promptly update your response following my comment). Reordering would make sense iif there's no natural grouping among items (which is often the case in strutured questionnaire), but I use it too because it is very convenient to display potential ceiling/floor effects. Now, the point is that a stacked barchart rarely conveys effective information about binary items (it seems more appropriate for ordered response categories, like Likert-type items) whereas dotchart can cope with both type of items. Here, the limiting factor is the No. items. – chl Dec 2 '10 at 9:26

For the coloring, either you specify a list of colors or you generate them.

In the latter, I suggest you execute this code

n = 32;
main.name = paste("color palettes; n=",n)
ch.col = c("rainbow(n, start=.7, end=.1)", "heat.colors(n)", "terrain.colors(n)",            "topo.colors(n)", "cm.colors(n)");

nt <- length(ch.col)
i <- 1:n;
j <- n/nt;
d <- j/6;
dy <- 2*d;

plot(i,i+d, type="n", yaxt="n", xaxt="n", ylab="", , xlab ="", main=main.name)   #yaxt="n" set no y axie label and tick.
for (k in 1:nt) {
rect(i-.5, (k-1)*j+ dy, i+.4, k*j, col = eval(parse(text=ch.col[k])), border = "grey");
text(2.5*j, k * j + dy/2, ch.col[k])
}


taken from the blog http://statisticsr.blogspot.com/2008/07/color-scale-in-r.html

Barplotting should be done with ?barplot

DF=data.frame(names=c("tomato", "potato", "cabbage", "sukuma-wiki", "terere"), freq=c(7,4,5,8,20))
barplot(as.matrix(DF[,2]), col=heat.colors(length(DF[,2])), legend=DF[,1], xlim=c(0,9), width=2)

-
 thanks about that but dont see how i can apply it before i draw the chart first – eastafri Dec 2 '10 at 7:09 something like that? This is simple data visualization, I suggest you read a few tutorials – RockScience Dec 2 '10 at 7:34 (+1) Good update. – chl♦ Dec 2 '10 at 7:37