1

Am trying to arrange the order of stacked bars using the following data frame:

DF <- structure(list(Group = structure(c(2L, 2L, 2L, 2L, 2L, 2L, 1L, 
                                     1L, 1L, 1L, 1L, 1L, 2L, 1L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 2L, 2L, 
                                     1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 1L, 2L, 1L, 1L, 1L, 1L, 
                                     1L, 2L, 1L), 
                                   .Label = c("1", "2"), class = "factor"), 
                 Response = structure(c(1L, 
                                        1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 
                                        2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 
                                        3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L), .Label = c("1", "2", "3"
                                        ), class = "factor"), Count = c(531L, 472L, 374L, 326L, 207L, 
                                                                        168L, 76L, 60L, 51L, 43L, 37L, 18L, 6L, 0L, 247L, 149L, 86L, 
                                                                        48L, 45L, 36L, 29L, 14L, 10L, 4L, 3L, 3L, 0L, 0L, 531L, 230L, 
                                                                        173L, 93L, 87L, 76L, 30L, 29L, 29L, 22L, 13L, 3L, 2L, 0L), 
                 Percent = c(85.23, 75.76, 60.03, 52.33, 33.23, 26.97, 12.2, 9.63, 8.19, 6.9, 5.94, 
                             2.89, 0.96, 0, 39.65, 23.92, 13.8, 7.7, 7.22, 5.78, 4.65, 2.25, 
                             1.61, 0.64, 0.48, 0.48, 0, 0, 85.23, 36.92, 27.77, 14.93, 13.96, 
                             12.2, 4.82, 4.65, 4.65, 3.53, 2.09, 0.48, 0.32, 0), 
                 Items = structure(c(4L, 2L, 3L, 5L, 7L, 1L, 4L, 5L, 2L, 3L, 7L, 1L, 6L, 6L, 7L, 1L, 3L, 
                                     5L, 2L, 7L, 1L, 4L, 6L, 3L, 2L, 5L, 4L, 6L, 6L, 1L, 5L, 7L, 3L, 
                                     6L, 2L, 1L, 3L, 2L, 5L, 7L, 4L, 4L), 
                                   .Label = c("A", "B", "C", "D", "E", "F", "G"), class = "factor")), 
            .Names = c("Group", "Response", "Count", "Percent", "Items"), 
            row.names = c("18", 
                          "36", "2", "8", "24", "42", "17", "7", "35", "1", "23", "41", 
                          "54", "53", "26", "44", "4", "10", "38", "25", "43", "20", "56", 
                          "3", "37", "9", "19", "55", "58", "46", "12", "28", "6", "57", 
                          "40", "45", "5", "39", "11", "27", "22", "21"), class = "data.frame")

library(ggplot2)

cPalette = c("#F8766D","#619CFF","#00BA38")

ggplot(DF, aes(x = Items, y = Percent, fill = Response,  order = Response )) + 
geom_bar(stat = "identity" ) +  
labs(title="Acceptance",
   x ="Items", y = "Percent") +
scale_fill_manual(values=cPalette,
                breaks=c("1","2","3"), 
                labels=c("Negative", "Neutral","Positive") ) +
theme(text = element_text(size=15, color = "blue", face = "bold"),
    axis.text.x = element_text(color = "black", face = "bold"), 
    axis.text.y = element_text(color = "black", face = "bold" ))

I would like to have the bars on the x-axis going from left to right: D,B,C,E,G,A,F instead of alphabetically A,B,C,D,E,F,G This should not be ordered manually because it depends on %age contribution of the factor within the stack.

Extensive search of SO gave me this link which comes closest to what I wish to achieve.

How does one get the bars to display left to right in decreasing order of negative Responses? I am stuck with this problem last couple of days.

Community
  • 1
  • 1
LGF
  • 103
  • 5
  • cPalette = c("#F8766D","#619CFF","#00BA38") Apologies for not inserting this line in the code. Added now. – LGF Aug 12 '15 at 04:20

1 Answers1

1

You can order the levels of Items by the percentage, then plot

## Order the Items by %Response == 1
agg <- aggregate(Percent ~ Items, data=DF[DF$Response==1,], sum)
DF$Items <- factor(DF$Items, levels=agg[order(agg$Percent, decreasing = T), "Items"])

## The plot as you had it
cPalette = c("#F8766D","#619CFF","#00BA38")
ggplot(DF, aes(x = Items, y = Percent, fill = Response,  order = Response )) + 
  geom_bar(stat = "identity" ) +  
  labs(title="Acceptance",
       x ="Items", y = "Percent") +
  scale_fill_manual(values=cPalette,
                    breaks=c("1","2","3"), 
                    labels=c("Negative", "Neutral","Positive") ) +
                      theme(text = element_text(size=15, color = "blue", face = "bold"),
                            axis.text.x = element_text(color = "black", face = "bold"), 
                            axis.text.y = element_text(color = "black", face = "bold" ))

enter image description here

Rorschach
  • 31,301
  • 5
  • 78
  • 129
  • +1 This does exactly what is required. I knew that the levels of Items needed to be ordered by percentage and struggled to find a successful way to do it. Your post educated me on how to use aggregate and factor levels. Thanks a ton! – LGF Aug 12 '15 at 05:00
  • @LGF glad to hear it! – Rorschach Aug 12 '15 at 05:01
  • I mean... no votes??!! +1 (and unfortunately, it's not enough, such a GREAT answer!!!) – umbe1987 Feb 11 '22 at 16:52