Home > Net >  Horizontal stacked bar chart with a separate element in ggplot
Horizontal stacked bar chart with a separate element in ggplot

Time:11-05

I'm trying to come up with a way to visualize some likert scale data in a specific way. I'm not even sure how to fake what it would look like, so I hope my explanation would suffice.

I have the following (fake) data:

n questions, each with 5 answers (strongly agree, agree, don't agree, strongly don't agree, and don't know)

I want to visualize the data (ideally using ggplot) along a central axis, so that the two "agree" answers are on the left, and the two "disagree" answers are on the right, and then on a separate block off to the side, a block representing "don't know". It should look roughly like this:

Q1:  *****        |------!!     ?????
Q2:     ****      |----!!!!!!   ???????
Q3:       **      |---!!!       ??????????
      *: strongly agree,  : agree, -: don't agree, !:strongly disagree, ?: don't know

As you can see, this representation allows to compare the actual numbers of agree and disagree, without hiding how many "don't knows" there are. The place I get stuck on is how to create that second element for the don't knows. Any ideas?

Here's some fake data:

structure(list(Q = structure(1:3, .Label = c("Q1", "Q2", "Q3"
), class = "factor"), SA = c(25, 18, 12), A = c(30, 25, 15), 
    DA = c(25, 20, 25), SDA = c(10, 18, 25), DK = c(10, 19, 23
    )), row.names = c(NA, -3L), class = "data.frame")

CodePudding user response:

As suggested in the comments, you can just facet out the "DK" category.

library(ggplot2)
library(tidyr)
library(scales)

df <- structure(list(Q = structure(1:3, .Label = c("Q1", "Q2", "Q3"
), class = "factor"), SA = c(25, 18, 12), A = c(30, 25, 15), 
DA = c(25, 20, 25), SDA = c(10, 18, 25), DK = c(10, 19, 23
)), row.names = c(NA, -3L), class = "data.frame")

lvls <- colnames(df)[c(2,3,5,4,6)]

ggplot(
  pivot_longer(df ,-1),
  aes(y = Q, fill = name, group = factor(name, lvls),
      x = ifelse(name %in% c("A", "SA"), -1, 1) * value)
)  
  geom_col()  
  facet_grid(~ name == "DK", scales = "free_x", space = "free_x")  
  scale_fill_manual(
    values = c(viridis_pal()(4), "grey50"),
    limits = colnames(df)[-1]
  )

Created on 2021-11-04 by the enter image description here

Then you can plot the dk with base R in case. Unluckily the plot made with the function above is class trellis and seems it does not like to be arranged. enter image description here

  • Related