stacked bar for five scales and four categories

Solution for stacked bar for five scales and four categories
is Given Below:

I need to present my data on staked bars. There are four categories for five scales and the sample size is 200

df <- tribble(
    ~ID, ~scale1,  ~scale2, ~scale3, ~scale4, ~scale5,
    "1",  "Cat1",    "Cat2",    "Cat4",   "Cat1",  "Cat2",
    "2",  "Cat3",    "Cat3",    "Cat1",   "Cat2",  "Cat3",
    "3",  "Cat4",    "Cat1",    "Cat2",   "Cat3",  "Cat2",
    "4",  "Cat1",    "Cat4",    "Cat2",   "Cat4",  "Cat4",
    "5",  "Cat2",    "Cat1",    "Cat3",   "Cat1",  "Cat1")

How to create a stacked bar for each scale?
I’ve tried this but it didn’t work

df=df %>%
  select(ID,scale1:scale5) %>%
  pivot_longer(cols=scale1:scale5,names_to="Scale",values_to = "Value")%>%
  mutate(Category=case_when(
    Value>=4 ~"Cat4",
    Value>=3 &Value<4 ~"Cat3",
    Value>=2 &Value<3 ~"Cat2",
    Value<2 ~"Cat1",
    TRUE ~ "None"
  )) %>%
  mutate(Category=factor(Category,levels = c("Cat4","Cat3","Cat2","Cat1")))%>%
  mutate(Scale=factor(Scale, levels =c("Math","Physics","","Computer","PE","English")))

Update on OP’s comment:
I will now show how to plot a stackbar with counts and percent. Most important is a tidy data. That is you should get an idea how to tidy your data before plotting.
Here is your example complete solution:

library(tidyverse)

# rename column names with vector
colnames(df) <- c("ID", "Math", "Physics", "_", "Computer","PE","English")


df1 <- df %>% 
    pivot_longer(
        cols = 2:6,
        names_to = "Scale",
        values_to = "Category"
    ) %>% 
    group_by(Scale, Category) %>% 
    count(Category) %>% 
    group_by(Scale) %>% 
    mutate(percent=n/sum(n)) %>% 
    print(n=40)


# plot count
ggplot(df1, aes(fill=Category, y=n, x=Scale)) + 
    geom_bar(position="stack", stat="identity") +
    geom_text(aes(label=paste0(n)),
              position=position_stack(vjust=0.5), colour="white", size = 5)


# plot with percent
ggplot(df1, aes(fill=Category, y=n, x=Scale)) + 
    geom_bar(position="fill", stat="identity") +
    geom_text(aes(label=paste0(sprintf("%1.1f", percent*100),"%")),
              position=position_fill(vjust=0.5), colour="white", size = 5) +
    scale_y_continuous(labels = scales::percent)

enter image description here

First answer:
You can achieve the same result by this code:

library(tidyverse)

# rename column names with vector
colnames(df) <- c("ID", "Math", "Physics", "_", "Computer","PE","English")

df %>%
    pivot_longer(cols= -ID ,names_to="Scale",values_to = "Category") %>% 
    ggplot(aes(fill=Category, x=Scale)) + 
    geom_bar(stat="count", position = 'stack')+
    theme_bw()
    

enter image description here

Is this what you are looking for? I changed up the last part of your code to include another mutate + case_when and I then I changed your fill to Value.

This was a little confusing because I don’t think your first mutate + case_when was doing anything and also there were only five scales in the data frame you shared so English didn’t show up anywhere.

df <- tribble(
    ~ID, ~scale1,  ~scale2, ~scale3, ~scale4, ~scale5,
    "1",  "Cat1",    "Cat2",    "Cat4",   "Cat1",  "Cat2",
    "2",  "Cat3",    "Cat3",    "Cat1",   "Cat2",  "Cat3",
    "3",  "Cat4",    "Cat1",    "Cat2",   "Cat3",  "Cat2",
    "4",  "Cat1",    "Cat4",    "Cat2",   "Cat4",  "Cat4",
    "5",  "Cat2",    "Cat1",    "Cat3",   "Cat1",  "Cat1")


df=df %>%
  select(ID,scale1:scale5) %>%
  pivot_longer(cols=scale1:scale5,names_to="Scale",values_to = "Value")%>%
  mutate(Category=case_when(
    Value>=4 ~"Cat4",
    Value>=3 &Value<4 ~"Cat3",
    Value>=2 &Value<3 ~"Cat2",
    Value<2 ~"Cat1",
    TRUE ~ "None"
  )) %>%
  mutate(Category=factor(Category,levels = c("Cat4","Cat3","Cat2","Cat1"))) %>%
    mutate(Scale=case_when(
    Scale=="scale1" ~"Math",
    Scale=="scale2" ~"Physics",
    Scale=="scale3" ~"",
    Scale=="scale4" ~"Computer",
    Scale=="scale5" ~"PE",
    Scale=="scale6" ~"English"))
    

ggplot(na.omit(df), aes(fill=Value, x=Scale)) + 
  geom_bar(stat="count", position = 'stack')+
  theme_bw()

enter image description here