How do I plot percentages for multiple response questions?

Viewed 157

I am trying to analyse a survey in which multiple responses are allowed for the same respondent. The goal is to determine the number of participants within each class that gave each of 3 possible responses, in order to plot it on a bar graph.

So for example, if my data frame df looks like follows:

ID q1 q2 q3 class
001 cat dog NA A
002 cat NA bird A
003 NA dog bird A
004 NA dog NA B
005 cat dog NA B
006 NA dog bird B
007 cat dog bird C
008 NA dog NA C

I would like to determine the percentage of respondents in class A, B, and C, respectively, who gave each answer. My expected answer looks like this:

class q perc
A cat 0.67
A dog 0.67
A bird 0.67
B cat 0.33
B dog 1.00
B bird 0.33
C cat 0.50
C dog 1.00
C bird 0.50

I would like to keep my answer as a data frame, since I would like to use the ggplot2 package to combine my resulting frequencies with other variables that I have (like the variable cls in the data frame above.

Right now I'm only able to determine the raw frequencies, since whenever I try to plot the percentages, I get the percentage with respect to the total number of answers per category. For example, for category A, I get: |class| q |perc| |--|--|--| |A| cat |0.33| |A| dog |0.33| |A| bird |0.33|

Here's what I've tried:

library(tidyr)
library(ggplot2)

idno <- 1:8
q1 <- c('cat','cat',NA, NA, 'cat',NA,'cat',NA)
q2 <- c('dog',NA,'dog','dog','dog','dog','dog','dog')
q3 <- c(NA,'bird','bird',NA,NA,'bird','bird',NA)
cls <- c('A','A','A','B','B','B','C','C')

df <- data.frame(idno,q1,q2,q3,cls)

df1 <- gather(df,"animal","ans",2:4)
ggplot(df1[!is.na(df1$ans),], aes(x=ans, group=cls)) + geom_bar(aes(y=..prop..,fill=cls),position='dodge')

Is there a way in which I can divide the frequency for each subcategory not by the number of answers but rather by the number of respondents in that category?

Current Graph

1 Answers

You must set the aesthetics y and label to ..prop.. and the position's width. vjust justifies the labels within the bars.

ggplot(df1[!is.na(df1$ans),], aes(x = ans, group = cls, fill = cls)) + 
  geom_bar(aes(y = ..prop..), position = position_dodge(width = 1)) +
  geom_text(aes(y = ..prop.., label = scales::percent(..prop..)),
            stat = 'count', position = position_dodge(width = 1), vjust = -0.5)

enter image description here

Related