3

I'm aware that this is a long-standing problem: setting unlabelled, customizable minor tick marks in ggplot2. I find this post containing a work-around to offer 2 solutions that are somewhat customizable the best, but won't work for me personally: Quick, sleek and simple way of adding minor ticks in ggplot2?.

To my understanding you just plot all major tick marks and set the labelling of some of these, the ones that are supposed to be minor tickmarks, to NULL or "". Thus, the minor tickmarks won't have a label, but the major tickmarks will. This works, but I would like my minor tickmarks to be smaller than major tickmarks and since you cant distinguish between the two here, it doesn't work.

I don't necessarily mind typing out where the minor ticks should be placed each time, as long as this is easy to do consistently.

Given the following fictional dataset and code, is it possible to make minor y-axis ticks here inbetween the major ticks at intervals to lets say every 0.25 that are smaller than the major ticks?

library(ggplot2)

# Create some sample data
set.seed(123)
data <- data.frame(group = rep(c("A", "B"), each = 50),
                   value = c(rnorm(50, mean = 10), rnorm(50, mean = 20)))

# Create the plot using ggplot2
p <- ggplot(data, aes(x = group, y = value)) +
  geom_boxplot()

# Duplicate the y-axis
p + scale_y_continuous(sec.axis = dup_axis()) + theme_classic()
pleasehelp
  • 87
  • 6

2 Answers2

3

You could use the ggh4x package with ggh4x.axis.ticks.length.minor with rel of for example 0.5 to make smaller ticks at certain minor_breaks like this:

library(ggplot2)
library(ggh4x)
# Create some sample data
set.seed(123)
data <- data.frame(group = rep(c("A", "B"), each = 50),
                   value = c(rnorm(50, mean = 10), rnorm(50, mean = 20)))

# Create the plot using ggplot2
p <- ggplot(data, aes(x = group, y = value)) +
  geom_boxplot()

# Duplicate the y-axis
p + scale_y_continuous(
  minor_breaks = seq(8, 22, by = 0.25),
  breaks = seq(8, 22, by = 4), limits = c(8, 22),
  guide = "axis_minor"
) +
theme(ggh4x.axis.ticks.length.minor = rel(0.5)) + 
theme_classic()

Created on 2023-01-09 with reprex v2.0.2

Quinten
  • 35,235
  • 5
  • 20
  • 53
  • Hi Quinten, I get the following error when adding the piece of code you suggested within the "scale_y_continous" call in my own code: **Error in ticks$.label[is_major] <- scale$get_labels(breaks[is_major]) : replacement has length zero** – pleasehelp Jan 09 '23 at 15:03
  • Hi @pleasehelp, This error means that you are assigning a value of length zero to the function. Are you sure you copied the code right? – Quinten Jan 09 '23 at 15:16
  • Hi Quinten, apologies, I copied parts of your code into the code I'm using to make a plot. Using your exact code on the example dataset works! Perhaps you take a quick glance at this piece of code and see where the problem is (I'm going for a boxplot, with axis surrounding the plot and ticks pointing inwards, hence the duplicated axes and negative values for ticklength) which has y-axis minor tick marks: – pleasehelp Jan 09 '23 at 16:55
  • `data %>% ggplot(aes(x=Line_num,y=log_FC, group=interaction(Line_num, Treatment))) + stat_boxplot(geom = 'errorbar', width=0.15, position = position_dodge(width=0.6)) + geom_boxplot(outlier.shape=NA, width=0.4, position = position_dodge(width=0.6)) + scale_y_continuous(limits=c(-3, 2), breaks = seq(-3, 2, by=1), minor_breaks = seq(-3, 2, by=0.25), sec.axis = dup_axis(name=NULL, labels=NULL)) + theme(axis.ticks.length = unit(-0.1, "cm")) + scale_x_continuous(sec.axis = dup_axis(name = NULL, labels = NULL)) + theme(axis.ticks = element_line(colour = 'black', size = 1)) ` – pleasehelp Jan 09 '23 at 16:57
  • @pleasehelp, why do you use `NULL` in your `dup_axis` arguments? – Quinten Jan 09 '23 at 16:59
  • Because, if I understand my own code correctly, it removes the second y-axis label and major tick labels. I typically dont use those, I just like to have axis around the plot if you have many groups (and thus boxes) so that the boxes fartest away from the primary y-axis are still close to another axis for checking values. I add the major tick values separately in annotation programs like Adobe Illustrator later, since these values often will either be plotted inside or outside the plot margins. Something that I'm too lazy to fix in the code. – pleasehelp Jan 09 '23 at 17:12
  • @pleasehelp, Could you please try with NA instead of NULL? – Quinten Jan 09 '23 at 17:13
  • Sorry this doesn't work. I get the following error: `Error in `get_labels()`: ! Invalid `labels` specification. Use "NULL", not "NA"` – pleasehelp Jan 09 '23 at 17:35
3

The {ggh4x} package has a guide function for adding minor tick marks.

For basic usage, you can add it by using the y = "axis_minor" in the guides() function.

library(ggplot2)
library(ggh4x)

# Create some sample data
set.seed(123)
data <- data.frame(group = rep(c("A", "B"), each = 50),
                   value = c(rnorm(50, mean = 10), rnorm(50, mean = 20)))

# Create the plot using ggplot2
p <- ggplot(data, aes(x = group, y = value)) +
  geom_boxplot()

p + guides(y = "axis_minor")

If you need more control over where they are placed, use the minor_breaks argument of the scale. If you want to control the length of the minor breaks, you can use the ggh4x.axis.ticks.length.minor theme setting. Note that it specifies the minor ticks length relative to the major tick length.

p + 
  scale_y_continuous(
    minor_breaks = scales::breaks_width(1),
    guide = guide_axis_minor()
  ) +
  theme(ggh4x.axis.ticks.length.minor = rel(2))

Created on 2023-01-09 with reprex v2.0.2

Disclaimer: I'm the author of ggh4x. Also, the guide function might become deprecated in 2 cycles of ggplot2 development.

teunbrand
  • 33,645
  • 4
  • 37
  • 63
  • that's interesting inside information. I've closed this question as the same solution was already suggested in the far more "famous" thread. Thanks as usual for your fantastic work – tjebo Jan 09 '23 at 15:40
  • 2
    Yeah I'm trying to smuggle minor axis ticks into vanilla ggplot2, so no need for me to maintain ggh4x's then ;D – teunbrand Jan 09 '23 at 15:59
  • 1
    If I can't smuggle it into ggplot2, I'll just go maintain a separate package for all the axis functions – teunbrand Jan 09 '23 at 16:01
  • May I suggest "ggh4xis". – tjebo Jan 09 '23 at 16:47
  • 1
    hahaha, nah it'll include other guides as well legends/colourbar variations and such – teunbrand Jan 09 '23 at 22:34