问题
I would like to create a combination bar plot where within data1 and data2 are stacked while between data1 and data2 are grouped in base R graphics.
Something like this in arrangement:
data1 <- matrix(c(1:5, rep(1,5), rep(4,5)), ncol=5)
data2 <- matrix(c(2:6, rep(2,5), rep(3,5)), ncol=5)
# stacked bar
barplot(data1)
#grouped var
barplot(data1, beside=TRUE)
Any idea how can I do this? I know we can do this using different plots or facets but I would like to present them side by side in a single plot.
回答1:
You can use the argument space
of barplot
to shift the second barplot:
# plot first barplot, using xlim to ensure there is enough space to plot the second one
# (here the spaces are all 0, so the bars are grouped together)
barplot(data1, space=0, xlim=c(-1, ncol(data1)+ncol(data2)+1), las=1)
# plot second barplot (with add=TRUE so the bars appear on the same plot),
# putting a space of 6 (the number of columns of data1 + 1) at the beginning,
# to plot the "new" bars on the right of the first bars (the other spaces are 0):
barplot(data2, space=c(ncol(data1)+1, rep(0, ncol(data2)-1)), las=1, add=TRUE)
回答2:
You can try using mfrow
to plot two plots side by side:
par(mfrow = c(1,2))
barplot(data1, ylim = c(0,13), xlab = "data1")
barplot(data2, ylim = c(0,13), axes = FALSE, xlab = "data2")
回答3:
I know you're looking for a base-R solution. That's a pitty. ggplot2 offers great possibilities for such tasks:
data3 = data.frame(data_nr = rep(c("data1","data2"), each=15),
cat_1 = rep(rep(letters[1:5], each=3),2),
cat_2 = rep(rep(LETTERS[1:3], 5),2),
height = c(1:5, rep(1,5), rep(4,5), 2:6, rep(2,5), rep(3,5)))
ggplot(data3, aes(x=cat_1, y=height, fill=cat_2)) +
geom_bar(stat="identity", position="stack") +
facet_grid(~ data_nr)
gives:
I can think of a (less elegant) solution in pure base-R using a little hack:
data12 = cbind(data1, rep(NA,3), data2)
barplot(data12, space=0)
gives:
回答4:
Here is custom function where you can manipulate between and within group plots and can be done with any number of the data you want to plot.
multistack.bar <- function(x=list(x), betweenspace = 2, withinspace=0, ...){
# note that number of rows in each component matrix of the list
# should be equal
# if you have missing value use "NA", to make it complete
# number of column can differ
mylist <- x
space = list()
space[[1]] <- c(rep(withinspace,ncol(mylist[[1]] )),betweenspace )
for ( i in 2:length(mylist)){
if(i == length(mylist)){
space[[i]] <- c(rep(withinspace,ncol(mylist[[i]] )-1))
} else{
space[[i]] <- c(rep(withinspace,ncol(mylist[[i]] )-1),betweenspace )
}
}
un.space <- c(unlist(space))
newdata <- do.call("cbind", mylist)
barplot(newdata, space= un.space, ...)
}
The following is example with three dataset. Note all data has same number of rows but the column is different. As the row values are stacked, should be same number but one can make the rows equal by putting NA or 0 for the group that is missing.
data1 <- matrix(c(1:5, rep(1,5), rep(4,5)), ncol=5)
data2 <- matrix(c(2:6, rep(2,5), rep(3,5)), ncol=5)
data3 <- matrix(c(2:6, rep(2,5), rep(3,5)), ncol=5)
data4 <- matrix(c(1:4, rep(1,4), rep(4,4)), ncol=4)
mylist <- list(data1, data2, data3, data4)
multistack.bar(mylist, betweenspace=3, withinspace=0.1,
col = c("pink", "blue", "purple"), xlab="groups", ylab="frequency", ylim = c(0, 16))
# you can decrease space between bars to 0 no space and between plots
multistack.bar(mylist, betweenspace=1, withinspace=0,
col = c("pink", "blue", "purple"), xlab="groups", ylab="frequency",
ylim = c(0, 16))
# now you can use any thing you want just make it elegant or useful.
legend(8, 14.8, c("A", "B", "C"), fill = c("pink", "blue", "purple"), ncol=3 )
abline(h=4, lty =2, col= "red")
回答5:
library(gridExtra)
data1 <- matrix(c(1:5, rep(1,5), rep(4,5)), ncol=5)
data2 <- matrix(c(2:6, rep(2,5), rep(3,5)), ncol=5)
# stacked bar
plot1 <- barplot(data1)
#grouped var
plot2<- barplot(data1, beside=TRUE)
grid.arrange(plot1, plot2, ncol=2)
来源:https://stackoverflow.com/questions/32997632/grouped-and-stacked-barplot-using-base-r