Joe Crozier
Joe Crozier

Reputation: 1036

R, ggplot, reverse y axes and draw bars from bottom

Hopefully this one is pretty easy, but I just can't seem to find the answer, though I have checked quite a few answers on here about flipping y-axes.

I have data like this:

df<-structure(list(applicant_name = structure(1:3, .Label = c("John Smith", 
"Lauren", "Billy"), class = "factor"), MeanRanking = c(11.5, 
8.25, 20)), row.names = c(NA, -3L), class = c("tbl_df", "tbl", 
"data.frame"))

I have a graph like this:enter image description here

And I'd like to flip it upside down as a lower score is "better". From what I find on here, scale_y_reverse can flip it upside down, but then my bars are drawn from the top, like so:

enter image description here

How do I put 0 at the top, the largest number at the bottom (the real data might get bigger than 12, the bottom could be 20 I supposed because it couldn't be bigger than that) and draw the bars/columns from the bottom?

Edit: seems like per the comments/answers geom_col may not work, but my aesthetic goal would be: the "biggest and tallest" bar would actually be for the smallest number. In the real world, this will be the applicant that will have the best placing "ranked in top 3" and so it'd be great if it kinda looked like the top of the podium per se. If that makes sense This is what I'd like: enter image description here

Upvotes: 1

Views: 1316

Answers (2)

Duck
Duck

Reputation: 39585

Maybe this can be close to what you want:

library(dplyr)
library(ggplot2)
library(tidyr)
#Code
df %>% mutate(Diff=abs(MeanRanking-max(MeanRanking))) %>%
  pivot_longer(-applicant_name) %>%
  mutate(value=-value,label=ifelse(name=='MeanRanking',abs(value),NA)) %>%
  ggplot(aes(x=applicant_name,y=value,fill=interaction(applicant_name,name)))+
  scale_y_continuous(labels = function(x) abs(x))+
  geom_bar(stat = 'identity')+
  geom_text(aes(label=label),vjust=-0.5,fontface='bold')+
  scale_fill_manual(values = c('tomato','cyan3','magenta',
                               'transparent','transparent','transparent'))+
  theme(legend.position = 'none')

Output:

enter image description here

Upvotes: 1

bouncyball
bouncyball

Reputation: 10761

I don't believe geom_col will work, because geom_col starts at 0 (or see this answer). We could use geom_segment instead, after doing a bit of data manipulation:

library(tidyverse) 

df %>%
    mutate(yy_max = max(MeanRanking)) %>%
    mutate(yy_min = yy_max - MeanRanking)  %>%
    ggplot(aes(applicant_name, yy_min, yend = yy_max, xend = applicant_name))+
    geom_segment(aes(colour = applicant_name), size = 3)+
    scale_y_reverse()

enter image description here

Upvotes: 1

Related Questions