Reordering grouped factors in a bar plot

Hello all,

How do I re-arrange the bars in my graph so that the x-axis variables stay grouped together and stay in the same exact order they are currently in, but the bar's height's are correct?

For some reason my code (below) is scrambling up the bar height....the columns with lower text labels have higher values. Also, the y-axis is off, since half of the bars have text labels above the max value. I'm not sure what is going on.

By the way the variables and axis names in this graph and data set are all renamed to be nonsensical. This is data from a study that is currently in collection and I would rather not post results at this time.

newdata%>%
  ggplot(aes(x=Movie,
             y=Loved_it,
             fill=Age))+ #fill indicates a grouping variable to color/sort by. Can also use "group="
  geom_col(stat = "identity", 
           position = position_dodge2(preserve = "single"), #_dodge puts columns next to one another; ()specifies distance between columns
           colour="black")+ #outline columns in black
   geom_text(aes(label = scales::comma(n)), #Label each column with text; include commas in labels if number hits 1,000+
            size = 2.5,
            position = position_dodge(width = 0.9), #center the labels over the columns
            vjust = 1)+ #vertically adjust the position of the labels x units from the column top 
  theme_light()+
  scale_y_continuous(labels = scales::comma)+
  labs(x = "Movie",
       y = "Count",
       title = "SW Prequal appreciation by age group")+
  theme(plot.title = element_text(hjust = 0.5))+ # this theme command centers the title
  theme(text = element_text(family = "Century Gothic",size = 10), #family= changes all fonts in the graph to the same font
        axis.title = element_text(face = "bold"),
        axis.text = element_text(face = "italic"),
        plot.title = element_text(face = "bold",size = 12))+
  scale_fill_manual(values = c("gray75","red"))+ #customize the fill colors used by the "fill=" call above
  theme(panel.grid = element_blank()) #remove gridlines

Rplot01 Rplot01

Without seeing your data I have to make some guesses. I tried to reproduce your data and graph. The first ggplot call attempts to reproduce your graph. In the second one I changed the y value to n, which may be closer to what you want. If this does not help you, can you post your fake data?

library(ggplot2)
library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union

newdata <- data.frame(Movie = rep(c("PhantomMenace", "AOTC", "ROTS"), each = 2),
                    Loved_it = c(59, 64, 59, 68, 60, 68),
                    Age = c("young", "old", "young", "old", "young", "old"),
                    n = c(66,68, 73, 70, 84, 72))
newdata <- newdata %>% mutate(Movie = factor(Movie, levels = c("PhantomMenace", "AOTC", "ROTS")),
                              Age = factor(Age, levels = c("young", "old")))
newdata
#>           Movie Loved_it   Age  n
#> 1 PhantomMenace       59 young 66
#> 2 PhantomMenace       64   old 68
#> 3          AOTC       59 young 73
#> 4          AOTC       68   old 70
#> 5          ROTS       60 young 84
#> 6          ROTS       68   old 72
newdata%>%
  ggplot(aes(x=Movie,
             y=Loved_it,
             fill=Age))+ #fill indicates a grouping variable to color/sort by. Can also use "group="
  geom_col(stat = "identity", 
           position = position_dodge2(preserve = "single"), #_dodge puts columns next to one another; ()specifies distance between columns
           colour="black")+ #outline columns in black
  geom_text(aes(label = scales::comma(n)), #Label each column with text; include commas in labels if number hits 1,000+
            size = 2.5,
            position = position_dodge(width = 0.9), #center the labels over the columns
            vjust = 1)+ #vertically adjust the position of the labels x units from the column top 
  theme_light()+
  scale_y_continuous(labels = scales::comma)+
  labs(x = "Movie",
       y = "Count",
       title = "SW Prequal appreciation by age group")+
  theme(plot.title = element_text(hjust = 0.5))+ # this theme command centers the title
  theme(text = element_text(family = "Century Gothic",size = 10), #family= changes all fonts in the graph to the same font
        axis.title = element_text(face = "bold"),
        axis.text = element_text(face = "italic"),
        plot.title = element_text(face = "bold",size = 12))+
  scale_fill_manual(values = c("gray75","red"))+ #customize the fill colors used by the "fill=" call above
  theme(panel.grid = element_blank()) #remove gridlines
#> Warning: Ignoring unknown parameters: stat


#Use n as the y value
newdata%>%
  ggplot(aes(x=Movie,
             y=n,
             fill=Age))+ #fill indicates a grouping variable to color/sort by. Can also use "group="
  geom_col(stat = "identity", 
           position = position_dodge2(preserve = "single"), #_dodge puts columns next to one another; ()specifies distance between columns
           colour="black")+ #outline columns in black
  geom_text(aes(label = scales::comma(n)), #Label each column with text; include commas in labels if number hits 1,000+
            size = 2.5,
            position = position_dodge(width = 0.9), #center the labels over the columns
            vjust = 1)+ #vertically adjust the position of the labels x units from the column top 
  theme_light()+
  scale_y_continuous(labels = scales::comma)+
  labs(x = "Movie",
       y = "Count",
       title = "SW Prequal appreciation by age group")+
  theme(plot.title = element_text(hjust = 0.5))+ # this theme command centers the title
  theme(text = element_text(family = "Century Gothic",size = 10), #family= changes all fonts in the graph to the same font
        axis.title = element_text(face = "bold"),
        axis.text = element_text(face = "italic"),
        plot.title = element_text(face = "bold",size = 12))+
  scale_fill_manual(values = c("gray75","red"))+ #customize the fill colors used by the "fill=" call above
  theme(panel.grid = element_blank()) #remove gridlines
#> Warning: Ignoring unknown parameters: stat

Created on 2020-01-04 by the reprex package (v0.3.0)

Please repost a repex. You can use the following as your dataset

suppressPackageStartupMessages(library(tidyverse)) 
dataset <- rownames_to_column(mtcars) %>% select(rowname,mpg,hp)
colnames(dataset) <- c("Movie", "Age", "Loved_it")
dataset <- tail(dataset,3)
dataset
#>            Movie  Age Loved_it
#> 30  Ferrari Dino 19.7      175
#> 31 Maserati Bora 15.0      335
#> 32    Volvo 142E 21.4      109

Created on 2020-01-04 by the reprex package (v0.3.0)

I figured out the odd discrepency....turns out that the bar heights are actually correct, but the text labels are incorrect and coming from the wrong column in the data. Here is the table I used to produce the graph:

> newdata
# A tibble: 6 x 5
  Age   Movie             n Loved_it Percent_Love
  <fct> <fct>         <int>    <int>        <dbl>
1 Young PhantomMenace    66       59         89.4
2 Old   PhantomMenace    68       63         92.6
3 Young AOTC             73       59         80.8
4 Old   AOTC             70       65         92.9
5 Young ROTS             84       60         71.4
6 Old   ROTS             72       65         90.3

It is the "Loved_it" dichotomous variable that I want plotted here, not the total n numbers, and that is indeed what is represented by the bars. However, the labels are coming from the n column instead of the same "Loved_it" column, and I'm not sure why.

You can see for example that PhantomMenace has 59 young people and 63 old people that liked it in the data frame, and this is correctly reflected on the y-axis of the graph...but the bars' labels come from the n column (66 and 68, respectively).

This part of the ggplot calls determines that the column n is used for the text.

geom_text(aes(label = scales::comma(n)),

Change the n to Loved_it to match the labels to the value of the bar heights.

1 Like

Awesome! I knew it must have been something simple that I overlooked. Thanks!!

Suppose that's what I get from copy-pasting lines from a tutorial without fully understanding it

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.