Reputation: 87
I have a dataframe with shares in percent,columns representing different items, rows the respective share of interviewees answering in different categories. I want to produce a stacked barchart.
library(ggplot2)
library(reshape2)
test<-data.frame(i1=c(16,40,26,18),
i2=c(17,46,27,10),
i3=c(23,43,24,10),
i4=c(19,25,20,36))
rownames(test)<-c("very i.","i.","less i.","not i.")
test.m<-melt(test)
ggplot(test.m, aes(x=variable, y=value, fill=value)) +
geom_bar(position="stack", stat="identity")
Looks o.k., but I want
a) center the bars: positive answers (very i. and i) up and the bottom two classes (less i. and not i.) down.
b) each category (very i, i, less i, not i,) having the same colour.
Any help would be much appreciated.
Upvotes: 6
Views: 7566
Reputation: 81693
It is better to use the category names as a separator instead of row names:
test$category <- factor(c(3,4,2,1), labels=c("very i.","i.","less i.","not i."))
(The ordering of the factor levels is done with repect to the stacked barplot (lowest: not i.
, highest: very i.
).
test.m <- melt(test)
To answer your questions:
category
is used for the fill
parameter to map each category to a different colour.The complete code:
ggplot(test.m, aes(x=variable, fill=category)) +
geom_bar(data = subset(test.m, category %in% c("less i.","not i.")),
aes(y = -value), position="stack", stat="identity") +
geom_bar(data = subset(test.m, !category %in% c("less i.","not i.")),
aes(y = value), position="stack", stat="identity")
Upvotes: 12
Reputation: 10478
Another tool that is designed exactly for this purpose is likert()
in the HH package. This sweet function plots diverging stacked barcharts appropriate for Likert, semantic differential, and rating scale data.
library(HH)
# note use of t(test)[,4:1] to transpose and mirror dataframe for easy plotting
# test dataframe is otherwise unaltered from OP's question
likert(t(test)[,4:1], horizontal = FALSE,
main = NULL, # or give "title",
xlab = "Percent", # becomes ylab due to horizontal arg
auto.key = list(space = "right", columns = 1,
reverse = TRUE))
One particularly appealing feature of likert()
is the ability to center a neutral response with the ReferenceZero argument. (Notice how it uses an appropriate grey color for the reference response):
likert(t(test)[,4:1], horizontal=FALSE,
main = NULL, # or give "title",
xlab = "Percent", # becomes ylab due to horizontal arg
ReferenceZero = 3,
auto.key=list(space = "right", columns = 1,
reverse = TRUE))
(These examples use vertical bars as is common, but horizontal=TRUE
is often better, especially if one wants to include question or scale names.)
Upvotes: 10