Search code examples
rbar-chartstacked

How to draw barplot with both stacked and sided bars in R?


I have three variables, support, party, and gender. Support has three levels, 1 for yes, 2 for no, and 3 for neural. Party and gender are dummy variables. Now let's fake them:

support = sample(1:3, size=100, replace=T)
party = as.numeric(rbinom(100, 100, 0.4) > 42)
gender = as.numeric(rbinom(100, 100, 0.4) > 39)

I want to see the percentage of support conditioned on party and gender. So far, I can do percentage conditioned on only one variable, say party.

counts = table(support,party)
percent = t(t(counts)/colSums(counts))
barplot(percent)

enter image description here

How can I split party by gender and place gender side-by-side while maintaining party support stacked in the current way? (If you don't understand what I am saying, read on ...)

To be clear, I want the first column bar 0 (party = 0) be split into two adjacent column bars, one for each gender. Then I want the second column bar 1 (party=1) be split into two adjacent column bars, one for each gender. For each specific column bar, I will want it to be stacked up like the way there are now.

I am not even sure this can be accomplished.

BY THE WAY, is there a way to control the width of the bars? They are way too wide for my taste.


Solution

  • How about something like this, we can call barplot twice to place two sets on the same surface. First, I named some of the data so I could keep track of it

    #sample data
    set.seed(15)
    support = sample(1:3, size=100, replace=T)
    party = factor(as.numeric(rbinom(100, 100, 0.4) > 42), levels=0:1, labels=c("D","R"))
    gender = factor(as.numeric(rbinom(100, 100, 0.4) > 39), levels=0:1, labels=c("M","F"))
    

    Now we summarize the data separately for each party

    tt<-table(support, gender, party)
    p1<-tt[,,1]
    p1<-p1/sum(p1)
    
    p2<-tt[,,2]
    p2<-p2/sum(p2)
    

    And now we combine the barplots

    xx<-barplot(p1, width=.3, space=c(.25,.6), xaxt="n", 
        xlim=c(0,2.4), ylim=c(0, max(colSums(p1), colSums(p2))))
    axis(1,xx, levels(gender), line=0, tick=F)
    yy<-barplot(p2, width=.3, space=c(5, .6), xaxt="n", add=T)
    axis(1,yy, levels(gender), line=0, tick=F)
    
    axis(1, c(mean(xx), mean(yy)), levels(party), line=1, tick=F)
    

    And this will produce

    enter image description here