Reputation: 654
I am trying to build a (somewhat) complex barplot in R. The idea is to overlay two charts, whereby the bars in one are wider than in the other one, such that both bars are always visible.
Here's what I have right now:
# GENERATE THE DATA
Age = c(50, 55, 60, 65, 70) # Age groups
Male = c(15.4, 24.3, 37.0, 54.6, 71.1) # Death rates for males
Female = c(8.4, 13.6, 19.3, 35.1, 50.0) # Death rates for females
Deathrate = matrix(c(Male,Female), nrow=length(Age), ncol=2, dimnames=list(Age, c("Male","Female")))
# GENERATE THE DATA
barplot(Deathrate[,1], col="red")
par(new=TRUE)
barplot(Deathrate[,2], space=1, col="blue")
Now, as you can see, the two plots are shown, but while both middle bars are nicely overlapping and centered, all other bars are not centered. For example, the rightmost blue bar is shown on the edge of the rightmost red bar.
Does anyone have a simple solution to center all bars?
Thanks, Philipp
PS I know that the chart isn't pretty (overlapping legends etc.)....
Upvotes: 1
Views: 3021
Reputation: 16035
barplot(as.vector(rbind(Male, Female)),col=c('red','blue'), space=rep_len(1:0,length(Male)*2), beside=T, legend.text=c('Male', 'Female'));
P.S. the bars are not centered, but I think they are prettier this way.
Upvotes: 1
Reputation: 7664
Here is a solution using ggplot2
Death.df <- as.data.frame(Deathrate) # ggplot2 requires a data frame
Death.df$ages <- rownames(Death.df) # add a column with rownames
Death.m <- melt(Death.df, id.vars = "ages") # melt the dataframe to long form
ggplot(Death.m) +
geom_histogram(aes(x = ages, y = value), stat = "identity", fill = "red", width = 0.4) +
geom_histogram(aes(x = ages, y = value), stat = "identity", fill = "blue", width = 0.5, position = "dodge") +
ggtitle("Death Rates of Males and Females\nMales in Red and Females in Blue")
Upvotes: 2
Reputation: 206243
barplot
certainly wasn't optimized for this case. It's not too hard to roll your own plotting function for this type of plot if you want even more control.
cbarplot <- function(x, ..., bcols=c("red","blue"), bwidth=c(.4,.3)) {
plot(1, type="n", xlim=c(.5,(nrow(x)+.5)), ylim=c(0,max(x)), xaxt="n", ...)
for(i in 1:ncol(x)) {
w <- bwidth[i]
rect(seq_len(nrow(x))-w, 0, seq_len(nrow(x))+w, x[,i], col=bcols[i])
}
axis(1, at=1:nrow(x), rownames(x))
}
cbarplot(Deathrate, ylab="Count", xlab="Age")
Upvotes: 1
Reputation: 22313
You can use add=TRUE
together with apropriate values for width
and space
.
barplot(Deathrate[,1], col="red")
barplot(Deathrate[,2], width=0.5, space=c(0.9, 1.4, 1.4, 1.4, 1.4), col="blue", add=TRUE)
Upvotes: 3