0
votes

Let's say I have 2 subjects. Each did experimental trials and control trials where the outcome for both sets of trials is either 1 or 0.

I want a stacked bar plot that shows the proportion of 1 responses and 0 responses for both types of trials for each subject.

So each subject would have two bars that both reach up to a proportion of 1.00 on the y axis.

Mock data

df1 <- data.frame(Sbj_ID = c(1),
              Trial_Type = c("Testing", "Testing", "Control", "Control"),
              Outcome = c(1, 0, 1, 0),
              Proportion = c(0.41, 0.59, 0.02, 0.98))

df2 <- data.frame(Sbj_ID = c(2),
              Trial_Type = c("Testing", "Testing", "Control", "Control"),
              Outcome = c(1, 0, 1, 0),
              Proportion = c(0.30, 0.70, 0.10, 0.90))

df <- merge(df1, df2, all=TRUE)

I want it to look like this type of figure, but with stacked bars

data(iris)
library(ggplot2)
library(tidyr)

iris %>%
  gather("Type", "Value",-Species) %>%
  ggplot(aes(Species, Value, fill = Type)) +
  geom_bar(position = "dodge", stat = "identity") 

Here are my failed attempts...

library(ggplot2)
library(tidyr)

# fail 1 
 df $>$
   gather("Outcome", "Proportion", -Sbj_ID) %>%
   ggplot(aes(Sbj_ID, Proporiton, fill = Outcome)) +
   geom_bar(stat = "identity", position = "dodge")

# fail 2 
 ggplot(df, aes( x = factor(Sbj_ID), y = Proportion, fill = Outcome)) +
   geom_bar(stat = "identity", position = "stack") 

Any ideas? Thank you in advance!

2

2 Answers

0
votes

My immediate suggestion would be to remove the position = "dodge" argument. ggplot2 will then stack the bars with frequency counts as shown below.

iris %>%
    gather("Type", "Value",-Species) %>%
    ggplot(aes(Species, Value, fill = Type)) +
    geom_bar(stat = "identity") 

enter image description here

If you would like to ensure that the stacked bars equal 1, you can add the argument position=position_fill(reverse=F) to the geom_bar() function.

iris %>%
    gather("Type", "Value",-Species) %>%
    ggplot(aes(Species, Value, fill = Type)) +
    geom_bar(stat = "identity",position=position_fill(reverse=F)) 

enter image description here

0
votes

Here's what I would do -

  • Convert Outcome and Sbj_ID to factor variables
  • Use facet_wrap to group by Sbj_ID

You're trying to 'stack' along Outcome but 'dodge' along Sbj_ID. So, using facet_wrap to handle Sbj_ID allows you to just use 'stack' for Outcome.

df  %>% 
 mutate(Outcome = as.factor(Outcome)) %>% 
 ggplot(aes(x = Trial_Type, y = Proportion, fill = Outcome)) + 
 geom_bar(stat = "identity", position = 'stack') +
 facet_wrap(vars(Sbj_ID))

See the output here