how to add minor axis and remove major axis by ggplot2?

59 views Asked by At

I have the following two questions: (1) I want to get the label to be between two ticks. My original thought was to add the secondary ticks and remove the primary ticks, but axis.minor.ticks.length.y doesn't work (2) Add stat_summary points at the legend Thank you very much for answering your questions!

Here is the code and figure:

library("ggplot2")
dt <- data.frame(
  ca = rep(c("Oesophageal cancer", "Gastric cancer", "Colorectal cancer"), 3),
  var1 = c(1:3, -4:-6, 7:9),
  var2 = rep(LETTERS[1:3], 3)
)

dt %>% 
  ggplot(aes(var1, ca, fill = var2))+
  geom_bar(stat="identity", width=0.8)+
  stat_summary(fun=sum, geom="point",colour="grey40", fill="grey40", shape=20, size=2)+
  geom_vline(xintercept=0, colour="grey30", linetype="dotted")+
  theme(
    axis.minor.ticks.length.y = rel(0.5)
  )

Objective: Change Figure 1 to Figure 2 style Figure 1 Figure 2

2

There are 2 answers

4
Allan Cameron On BEST ANSWER

You need to convert to a continuous scale to use minor ticks, since there are no minor breaks on a discrete axis:

dt %>% 
  ggplot(aes(var1, as.numeric(factor(ca)), fill = var2)) +
  geom_col(width = 0.8, orientation = 'y') +
  stat_summary(orientation = 'y', fun = sum, geom = "point", colour = "grey40", 
               fill = "grey40", aes(shape = 'average'), size = 2) +
  geom_vline(xintercept=0, colour="grey30", linetype = "dotted") +
  scale_y_continuous('ca', labels = levels(factor(dt$ca)), 
                     breaks = seq_along(levels(factor(dt$ca)))) +
  scale_shape_manual(NULL, values = 20) +
  guides(y = guide_axis(minor.ticks = TRUE), 
         fill = guide_legend(order = 1),
         shape = guide_legend(order = 2)) +
  theme(axis.minor.ticks.length.y = unit(3, 'mm'),
        axis.ticks.length.y = unit(0, 'mm'),
        legend.key = element_blank())

enter image description here

0
Bastián Olea Herrera On

As far as I know, ggplot2 doesn't have the functionality to add secondary ticks between axis breaks for discrete scales. But thanks to ggplot2's flexibility, we can add them manually without much hassle, just by drawing some lines (segments) just on the vertical axis, and adding a setting using coord_cartesian so that graphic elements out of the plot's boundaries don't get removed.

To position the ticks on the vertical axis of a discrete variable between each text label, we have to create a sequence of numbers equal to the axis breaks minus 0.5, because discrete values mapped to an axis have a numeric vertical position, so subtracting 0.5 will give us the middle position between each label.

To draw outside of the plot boundaries, we have to add hard limits for the x axis that will allow us to draw elements in the plot without stretching the vertical axis to fit them, because by default ggplot wants all plotted elements inside the plot area, and will stretch the axes to fit them. We do this in the limits_x_axis object.

library(ggplot2)
library(dplyr)

dt <- data.frame(
  ca = rep(c("Oesophageal cancer", "Gastric cancer", "Colorectal cancer"), 3),
  var1 = c(1:3, -4:-6, 7:9),
  var2 = rep(LETTERS[1:3], 3)
)

#values for the y axis
middle_ticks_positions <- seq(0.5, length(unique(dt$ca))+0.5, by = 1)

#limits for the x axis
limits_x_axis <- c(min(dt$var1)*1.2, max(dt$var1)*1.5)

dt %>% 
  ggplot(aes(var1, ca, fill = var2))+
  geom_bar(stat="identity", width=0.8)+
  annotate("segment", 
           x = -8.2, xend = -8.6, #adjust the length of ticks as you need
           y = middle_ticks_positions, yend = middle_ticks_positions) +
  coord_cartesian(clip = "off", xlim = limits_x_axis) +
  stat_summary(fun=sum, geom="point",colour="grey40", fill="grey40", shape=20, size=2)+
  geom_vline(xintercept=0, colour="grey30", linetype="dotted")+
  theme(
    axis.ticks.y = element_blank()
  )

ggplot with ticks between text labels