Home > front end >  Adding labels to a dual axis that are non-related to datapoints in ggplot
Adding labels to a dual axis that are non-related to datapoints in ggplot

Time:02-08

I am attempting to create a barplot that has has labels on a dual axis but for whom these new labels are not related or a transformation of the labels/values on the main axis. I.e., I can't use sec.axis.

I am looking to add the numbers from data$unknown for each year period (see plot below).

I am not sure if this is possible at all - using the data directly? Alternatively one could add text with annotate() - but this also doesn't seem to work for me.

Anybody in here who has a solution?

library('tidyverse')
library('scales')



data <- tibble(model = rep(c("model 0", "model I", "model II", "model III", "model IV"),3),
                year = c(rep('2005-2009', 5), rep('2010-2014',5), rep('2015-2017',5)),
                value = c(0.0, 10.4, 30.7, 26.7, 32.2, 0.0, 9.9, 31.0, 26.5, 32.6, 0.0, 19.1, 29.6, 25.6, 25.7),
                unknown = c(rep(30,5), rep(40,5), rep(27,5)))


p1 <- ggplot(data, aes(fill=model, y=value, x=year))   
  geom_bar(stat='identity', position = position_fill(reverse = TRUE))  
  scale_fill_grey(start=0.8, end=0.2)  
  theme_bw()  
  ggtitle('Model')  
  xlab('')   ylab('')  
  theme(legend.position="bottom",
        plot.title = element_text(hjust = 0.5),
        legend.title=element_blank(),
        text = element_text(family = "serif")
  )  
  scale_y_continuous(labels = percent_format(scale = 100))  
  scale_x_discrete(limits = rev(levels(data$year)))  
  coord_flip()
p1

In the plot below I have manually (outside of R) added the labels in order to clarify the question.

enter image description here

CodePudding user response:

The issue is that discrete positional scales do not allow for a secondary or duplicated axis, i.e. the have no sec.axis argument.

However, one option would be to make use of a continuous scale by converting your year variable to a numeric and making use of dup_axis.

Note 1: To create the labels for the secondary scale I create a named vector to make sure that the right values of your unknown gets assigned to each level of year.

Note 2: I dropped coord_flip and switched the role of x and y. Also, as we now have numerics on both axes I forced the horizontal bars via orientation="y".

library('tidyverse')
library('scales')

# Numeric year
data$year_num <- as.numeric(factor(data$year))
# Labels for primary scale
labels <- levels(factor(data$year))
# Labels for secondary scale
dup_labels <- distinct(data, year, unknown) %>% tibble::deframe()

p1 <- ggplot(data, aes(fill=model, x=value, y = year_num))   
  geom_bar(stat='identity', position = position_fill(reverse = TRUE), orientation = "y")  
  scale_fill_grey(start=0.8, end=0.2)  
  theme_bw()  
  ggtitle('Model')  
  xlab('')   ylab('')  
  theme(legend.position="bottom",
        plot.title = element_text(hjust = 0.5),
        legend.title=element_blank(),
        text = element_text(family = "serif")
  )  
  scale_x_continuous(labels = percent_format(scale = 100))  
  scale_y_continuous(breaks = seq_along(labels), labels = labels, sec.axis = dup_axis(labels = dup_labels))
p1

  •  Tags:  
  • Related