Thomas
Thomas

Reputation: 195

How to plot a series of stacked histograms in R and ggplot 2?

I have several likert-type survey questions around attitudes on foreign policy including Syria (syria_threat), North Korea (nk_threat), and Brexit (brexit). Each response is coded as a factor: "No Threat", "Slight Threat", "Medium Threat", "High Threat", and "Grave Threat." A minimal data example is given below

#Reading the data#
syria_threat<-c("High Threat", "Slight Threat", "Slight Threat", "Medium Threat")
nk_threat<-c("Grave Threat", "Grave Threat", "High Threat", "Medium Threat")

brexit<-c("Medium Threat", "Slight Threat", "Slight Threat", "No Threat")

data<-cbind.data.frame(syria_threat, nk_threat, brexit)

#Showing the structure of the data 
 data
   syria_threat     nk_threat        brexit
1   High Threat  Grave Threat Medium Threat
2 Slight Threat  Grave Threat Slight Threat
3 Slight Threat   High Threat Slight Threat
4 Medium Threat Medium Threat     No Threat

I would like to create a stack of histogram density plots that visualizes the perceived threat for each threat/crisis. So for each question (Syria, North Korea, and Brexit) I would have a histogram from No Threat to Grave stacked one on top of the other. Not all of the questions have all the same values (i.e., nobody saw Brexit as a "Grave Threat"). I would like it to look something like the answer to this question Multiple histograms in ggplot2 (but with the histogram bars rotated 90 degrees https://i.sstatic.net/3CPOS.png).

I am using the following code:

 ggplot(melt(data), aes(x=as.factor(value), fill=as.factor(value))) + 
 geom_bar() + xlab("") + 
 scale_fill_discrete("Threat")

And am getting the following error message:

Using syria_threat, nk_threat, brexit as id variables
Error in is.factor(x) : object 'value' not found

Any help would be appreciated. Thanks!

Upvotes: 1

Views: 228

Answers (1)

tyluRp
tyluRp

Reputation: 4768

So for each question (Syria, North Korea, and Brexit) I would have a histogram from No Threat to Grave stacked one on top of the other.

Based on that, I think you want the following:

library(tidyverse)

# Converting factors to characters
data[] <- lapply(data, as.character)

data %>% 
  gather(key, value) %>% 
  group_by(key, value) %>% 
  mutate(count = n()) %>% 
  distinct() %>% 
  ggplot(aes(value, count, fill = value)) +
  geom_col(position = position_dodge()) +
  facet_wrap(~ key, ncol = 1) +
  coord_flip() +
  scale_x_discrete(limits = c("No Threat", 
                              "Slight Threat", 
                              "Medium Threat", 
                              "High Threat", 
                              "Grave Threat")) +
  theme_bw() +
  theme(
    text = element_text(family = "Source Code Pro"),
    panel.grid.minor = element_blank(),
    panel.grid.major.y = element_blank()
    )

enter image description here

Note: I'm using tidyr instead of reshape2 since tidyr is meant to replace reshape2. Also, ignore/modify the theme components if you don't want them (for example, you might not have the Source Code Pro font installed).

Upvotes: 1

Related Questions