-1

I followed the answer on this question: Cluster stacked bargraph

to create the above graph: enter image description here

Using the following code:

test  <- data.frame(person=c("8.3. The number of people coming to me \n me, who
                             are who want pizza are too many \n,
                             and too aggressive.", "group 2", "group 3", "5", "6"), 
                    value1=c(100,150,120,100,100),  # Agree   
                    value2=c(25,30,45,100,100) ,    # Neutral
                    value3=c(25,30,45,100,100),     # Disagree
                    value4=c(100,120,150,100,100),  # Agree
                    value5=c(10,12,15,100,100),     # Neutral
                    value6=c(50,40,70,100,100))     # Disagree

library(reshape2) # for melt

melted <- melt(test, "person")

melted$cat <- ''
melted[melted$variable == 'value1' | melted$variable == 'value2' | melted$variable == 'value3',]$cat <- "GP"
melted[melted$variable == 'value4' | melted$variable == 'value5'| melted$variable == 'value6',]$cat <- "LW"
melted$gender <- ''
melted[melted$variable %in% sprintf("value%i",c(1,4)),]$gender <- "Agree"
melted[melted$variable %in% sprintf("value%i",c(2,5)),]$gender <- "Disagree"
melted[melted$variable %in% sprintf("value%i",c(3,6)),]$gender <- "Neutral"



p = ggplot(melted, aes(x = cat, y = value, fill = gender)) 

p + geom_bar(stat = 'identity', position = 'stack') +   facet_grid(~ person) + 
  scale_fill_manual(values = c("orangered","green","dodgerblue2")) + 
  theme(panel.background = element_rect(fill = 'white'))

My question is:

How do I fix the order of the stacks so that neutral is between agree and Neutral? Is there anyway to make the graph horizontal so that I can have more wide space to fit the question? I also want the numbers to show inside each bar, for example, the left most red bar should have 100 written inside it.

I have used some of the liekert libraries in R and Python but I was not able to group the bars and also there were other issues. This ggplot graph is the closest I have come to creating the chart I need, so I would appreciate if your answer is fully reproducible with the numbers I gave.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83

1 Answers1

2

To achieve your desired result you could

  1. set the factor levels in the desired order
  2. make use of coord_flip() to make a horizontal bar plot where I slightly changed the facet_grid to put the strips on the right and rotated the strip text labels.
  3. add the labels via geom_text where I set the position to position_stack(vjust = .5) to put the labels in the middle of the bars


melted$gender <- factor(melted$gender, c("Agree", "Neutral","Disagree"))
p = ggplot(melted, aes(x = cat, y = value, fill = gender))
p + geom_bar(stat = 'identity', position = 'stack') +
  geom_text(aes(label = value), position = position_stack(vjust = .5)) +
  facet_grid(person~.) + 
  scale_fill_manual(values = c("orangered","green","dodgerblue2")) + 
  theme(panel.background = element_rect(fill = 'white'),
        strip.text.y = element_text(angle = 0)) +
  coord_flip()

stefan
  • 90,330
  • 6
  • 25
  • 51
  • This works great! Do you know how I can add % signs to the numbers in the chart? – Kushal Mohnot Jun 05 '21 at 02:19
  • The most simple way to add a "%" is to you make use of `paste0`: `geom_text(aes(label = paste0(value, "%")), ...)`. However, as far as I get it the numbers in your plot are frequencies and not percentages? If this is the case I would suggest to add a column with the percentages to your df e.g. using dplyr you could do `melted <- group_by(melted, cat, person) %>% mutate(pct = 100 * value / sum(value))` and use `pct` instead of `value` in your plot. – stefan Jun 05 '21 at 08:24
  • 1
    Oh I just put some dummy data for stack exchange, the actual data is in %. Thank you so much for all your help! – Kushal Mohnot Jun 05 '21 at 13:51