0

I need to produce a simple column bar plot with the y-axis reversed, but without simply flipping the entire plot with scale_y_reverse. The scoring measurement is reversed in my use case, that is, smaller values rank higher. I also need to add an average score reference line to the plot. For example:

library(tidyverse) df <- data.frame(Score = c(1,3,3,4,6,5,7), Entity = c("A","B","C","D","E","F","G")) ggplot(df,aes(Entity,Score))+ geom_col()+ geom_hline(yintercept = mean(df$Score)) + scale_y_reverse() 

which produces the following plot on the left. I need to write my code such that it produces the plot on the right.

enter image description here

I have tried converting the score to a factor variable, but then I'm unable to plot the geom_hline because the axis is no longer continuous but rather discrete. Furthermore, I suppose you can hard code it with geom_segment, but I need to find a better solution because I'm implementing the plot in a shiny application which requires dynamic entity selection (that is, it's not always the same entities).

Another idea could be to mutate the Score column such that df %>% mutate(ScoreRev=7-Score), which will produce the right contents of the plot, but then I will need to manually override the y-axis labels without changing the contents. If that makes sense.

EDIT:

After reading R ggplot change labels of axis without changing the scale I found another alternative.

library(tidyverse) df <- data.frame(Score = c(1,3,3,4,6,5,7), Entity = c("A","B","C","D","E","F","G")) df <- df %>% mutate(ScoreRev = 7-Score) ggplot(df,aes(Entity,ScoreRev))+ geom_col()+ geom_hline(yintercept = mean(df$ScoreRev))+ scale_y_continuous(labels = function(x) label_parsed(paste(7-x))) 

enter image description here

1 Answer 1

3

This approach comes with the warning that it is very much off-label use of ggplot2, and involve some of its inner workings.

Because geom_col() at some point in the plot building process gets converted to a rectangle with xmin/xmax/ymin/ymax parameters, we can insert a value for one of these using the after_scale() function. Because under the hood the reversed scale just does -1 * x, we can pick a value of -7 to anchor the bars at 7.

It isn't an approved aesthetic for geom_col(), so you'll get a warning though.

library(tidyverse) df <- data.frame(Score = c(1,3,3,4,6,5,7), Entity = c("A","B","C","D","E","F","G")) ggplot(df,aes(Entity,Score))+ geom_col(aes(ymax = after_scale(-7)))+ geom_hline(yintercept = mean(df$Score)) + scale_y_reverse() #> Warning: Ignoring unknown aesthetics: ymax 

Created on 2022-02-02 by the reprex package (v2.0.0)

Sign up to request clarification or add additional context in comments.

1 Comment

Great thanks. I just figured out another way to do it getting inspiration from stackoverflow.com/questions/61395755/…. I'll post in the edit.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.