Reputation: 99
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.
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)))
Upvotes: 0
Views: 392
Reputation: 38063
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)
Upvotes: 3