'Displaying percentages within category for continuous/ordered variable (with ggplot)

I have two questions, the first a (hopefully) straightforward mechanical one and the second more theoretical (though still with a technical element).

  1. I am trying to do something nearly identical to this question, but I have a variable that is ordered/continuous (0 - 4), instead of a 1/0 dichotomous variable, which means that filtering == 1 will not work. To summarize here, I simply want to display the percent of each level within each race category.

  2. I am also hoping to figure out a way to display those descriptive results for all 3 questions in just one figure. I first thought about trying to do some type of facet_wrap() with each variable (question1, question2, question3) being its own panel. Would that require pivot_longer() to make my data long instead of wide? Another thought was to have just one figure/panel, but each x axis tick is a race category instead of a question, and then it'd have 3 bars for each of the 3 questions. I'm not sure how I'd get that to work, though.

Thanks in advance and sorry for this wordy question. Here is some example data:

set.seed(123)

d <- data.frame(
  race = sample(c("White", "Hispanic", "Black", "Other"), 100, replace = TRUE),
  question1 = sample(0:4, 100, replace = TRUE),
  question2 = sample(0:4, 100, replace = TRUE),
  question3 = sample(0:4, 100, replace = TRUE)
)


Solution 1:[1]

Here is a modification of @DaveArmstrong's very good solution+1:

library(tidyverse)
library(RColorBrewer)

sPalette <- "Purples" %>% 
  sapply(., function(x) brewer.pal(8, name = x)) %>% 
  as.vector

d %>% 
  pivot_longer(-race) %>%
  count(name, race, value) %>% 
  group_by(name, race) %>%
  mutate(value = as.factor(value),
         pct= prop.table(n) * 100) %>% 
  ggplot(aes(x=race, y=pct, fill=value)) + 
  geom_col(position = position_fill()) +
  facet_wrap(.~name)+
  labs(x="", y="Percentage (within Race)", fill="Response") + 
  scale_y_continuous(labels = scales::percent) +
  geom_text(aes(label =  round(pct, 1)),
            position = position_fill(vjust = .5)) +
  scale_fill_manual(values = sPalette) + 
  theme_classic()+
  theme(legend.position = "top", 
        panel.grid = element_blank(), 
        axis.text.x = element_text(angle = 45, hjust=1))

enter image description here

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 TarJae