12

I have a plot using ggplot2 in which I'd like many ticks along the x-axis, yet only some of the ticks will have tick labels associated with them. However, I'd like the tick marks for those that have labels to be longer than those that don't.

baisong
  • 123
  • 1
  • 5
  • Does this answer your question? [Adding minor tick marks to the x axis in ggplot2 (with no labels)](https://stackoverflow.com/questions/14490071/adding-minor-tick-marks-to-the-x-axis-in-ggplot2-with-no-labels) – Bruno Mioto Dec 22 '22 at 12:04

4 Answers4

10

In base R, you can suppress the x-axis with the initial plot call (with xaxt='n'), and then use tcl to control tick length (see ?par) with two axis(1, ...) calls.

plot(1:10, xaxt='n', ylab='', las=1)
axis(1, at=1:10, tcl=-0.8)
axis(1, at=seq(0, 11, 0.2), labels=NA)

enter image description here

jbaums
  • 27,115
  • 5
  • 79
  • 119
  • 2
    Nice, but OP asked for ggplot, not base R graphics – smci Jan 08 '15 at 21:57
  • 3
    @smci Doesn't matter, still awesome. – David Arenburg Jan 08 '15 at 21:59
  • 1
    @scmi - I saw the tag after I'd already posted (it's a good idea to include your key requirements _in the post_). Regardless, it doesn't hurt to have a base R solution here since people who _want_ to use base may stumble upon this question. – jbaums Jan 08 '15 at 21:59
  • 1
    This answer is awesome, but in general using R base graphics is going down a road that very quickly limits you and causes crufty non-extensible non-reusable code that's barely legible. Eventually you throw it out and switch to ggplot (or other library). Unless it's for a specific plotting type not well-served by ggplot. – smci Jan 08 '15 at 22:05
  • 1
    Fair point. Though I find that in some cases plotting with base graphics is much simpler than the `ggplot`/`lattice` equivalents, but that's possibly because I haven't put in enough time to learn the latter (it's on my to do list). As always with R, there are many ways to skin a cat, and IMO it's great for SO to present alternative solutions to a problem. :) – jbaums Jan 08 '15 at 22:15
  • Could anyone help using ggplot2 to produce the figure above? It seems quite challenging. – baisong Jun 03 '15 at 21:13
6

This is easier with base graphics, but here is an attempt using ggplot2.

The method is based on this method, which inserts blank labels into the sequence of labels (using code from that answer). Once the breaks and labels are in place in the ggplot, I burrow into the structure of the plot to edit the lengths of the tick marks. (Use with care; it would not be hard to break this.)

library(ggplot2)
library(grid)

# Data
 df = data.frame(x = 1:10, y = 1:10)

# Range of x values
range = 1:10

# Major tick marks
major = 1

# Minor tick marks
minor = 0.2

# Function to insert blank labels
# Borrowed from https://stackoverflow.com/questions/14490071/adding-minor-tick-marks-to-the-x-axis-in-ggplot2-with-no-labels/14490652#14490652
insert_minor <- function(major, n_minor) {
      labs <- c(sapply(major, function(x, y) c(x, rep("", y) ), y = round(n_minor)))
      labs[1:(length(labs) - n_minor)]
}

# Getting the 'breaks' and 'labels' for the ggplot
n_minor = major/minor - 1
breaks = seq(min(range), max(range), minor)
labels = insert_minor(seq(min(range), max(range), major), n_minor)
if(length(breaks) > length(labels)) labels = c(labels, rep("", length(breaks) - length(labels)))

# The plot
p <- ggplot(df, aes(x = x, y = y)) + 
     geom_point() + 
     scale_x_continuous(breaks = breaks, labels = labels) + 
     coord_cartesian(xlim = range) +
     theme_bw() +
     theme(panel.grid = element_blank(),
           axis.text.x = element_text(margin = margin(t = 5, unit = "pt")))
p

# Edit the plot:
# Change the lengths of the major tick marks

g = ggplotGrob(p)

# Get the x axis
xaxis <- g$grobs[[which(g$layout$name == "axis-b")]]  

# Get the tick marks and tick mark labels   
ticks <- xaxis$children[[2]]

# Get the tick marks
marks = ticks$grobs[[1]]

# Edit the y positions of the end points of the tick marks
# The '6' and the '3' in the code below 
# are the lengths in pts of the major and minor tick marks respectively. 
marks$y = unit.c(unit.c(unit(1, "npc") - unit(6, "pt"), unit(1, "npc"),   
                 rep(unit.c(unit(1, "npc") - unit(3, "pt"), unit(1, "npc")), n_minor)))

# Put the tick marks back into the plot
ticks$grobs[[1]] = marks
xaxis$children[[2]] = ticks
g$grobs[[which(g$layout$name == "axis-b")]]  = xaxis

# Draw the plot
grid.newpage()
grid.draw(g)

enter image description here

Community
  • 1
  • 1
Sandy Muspratt
  • 31,719
  • 12
  • 116
  • 122
  • 1
    This worked for me. Except I alter the line where you reset your marks to the following: `marks$y[seq(1,length(marks$y),2)][-seq(1,length(marks$y)/2, n_minor+1)] <- unit(1,'npc') - unit(3,'pt')` Using this way, you also should set the `axis.ticks.length = unit(6, "pt")` in the theme. – aaiezza Jan 16 '17 at 19:29
  • 2
    *Note:* We've adapted this solution for facett gridded plots, see: https://stackoverflow.com/q/53660703/6574038 – jay.sf Dec 09 '18 at 15:50
  • It's absurd that there's not a more elegant solution for this with ggplot2 theming 4 years later! Although, after much searching, there is a solution from the [ggh4x package](https://teunbrand.github.io/ggh4x/articles/PositionGuides.html#minor-ticks) – mattador Jul 29 '21 at 14:46
1

You can use the ggh4x package (look at the x-axis)

More info at: https://teunbrand.github.io/ggh4x/articles/PositionGuides.html#minor-ticks

library(ggplot2)
library(ggh4x)
library(dplyr)

tibble(
  x = 0,
  y = 0,
) %>% 
ggplot(aes(x=x, y=y))+
  geom_point()+
  scale_x_continuous(
    guide = "axis_minor"
    )

Created on 2022-12-20 with reprex v2.0.2

Bruno Mioto
  • 382
  • 1
  • 10
0

theme(axis.ticks.length)

http://docs.ggplot2.org/0.9.2.1/theme.html should be useful.

Edit Sorry, just read your question more carefully. Are the labeled ones the standard major.grid ticks? or labeled in some custom way?

Andrew Taylor
  • 3,438
  • 1
  • 26
  • 47
  • 1
    They are major.grid ticks, using `theme(axis.ticks.length)` will define the length of all ticks, not only those with labels. – baisong Jan 09 '15 at 22:25