1
votes
r - ggplot2: shorter tick marks for tick marks without labels (for y axis) - Stack Overflow
Asked
Viewed 1k times
1

I'm trying to replicate an answer by @sandy-muspratt here : ggplot2: Have shorter tick marks for tick marks without labels

but I'd like to add shorter tick marks for the y axis. The original code is

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://stackguides.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)

I tried to modify the code to make it work for the y axis, but was not able to get longer lines for the major tick marks:

library(ggplot2)
library(grid)

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

# Range of y values
range = 1:10

# Major tick marks
major = 1

# Minor tick marks
minor = 0.2

# Function to insert blank labels
# Borrowed from https://stackguides.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_y_continuous(breaks = breaks, labels = labels) + 
     coord_cartesian(ylim = range) +
     theme_bw() +
     theme(panel.grid = element_blank(),
           axis.text.y = 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
yaxis <- g$grobs[[which(g$layout$name == "axis-l")]]  

# Get the tick marks and tick mark labels   
ticks <- yaxis$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$x = 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
yaxis$children[[2]] = ticks
g$grobs[[which(g$layout$name == "axis-l")]]  = yaxis

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

I'd greatly appreciate any help making this work. Thank you.

    1

    The main issue is that you should be using marks = ticks$grobs[[2]]. There were some other issues with your code (which give's a warning 'data length is not a multiple of split variable') so here is a working minimal example:

    labs = seq(0,100,10)
    labs[!!((seq_along(labs)-1)%%5)] = ''
    g = ggplot(data.frame(x = 1:10, y = (1:10)^2), aes(x,y)) +
      geom_point() +
      scale_y_continuous(breaks = seq(0,100,10), labels = labs) +
      theme(axis.ticks.length=unit(10, "pt"))
    
    gg = ggplotGrob(g)
    yaxis <- gg$grobs[[which(gg$layout$name == "axis-l")]]  
    ticks <- yaxis$children[[2]]
    marks = ticks$grobs[[2]]
    marks$x[c(2:5,7:10)*2-1] = unit(1, "npc") - unit(3, "pt")
    
    # Put the tick marks back into the plot
    ticks$grobs[[2]] = marks
    yaxis$children[[2]] = ticks
    gg$grobs[[which(gg$layout$name == "axis-l")]]  = yaxis
    grid.draw(gg)
    

    enter image description here

    1

    Your Answer

    By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

    Not the answer you're looking for? Browse other questions tagged or ask your own question.

     
    1

    1 Answers

    1
    votes

    The main issue is that you should be using marks = ticks$grobs[[2]]. There were some other issues with your code (which give's a warning 'data length is not a multiple of split variable') so here is a working minimal example:

    labs = seq(0,100,10)
    labs[!!((seq_along(labs)-1)%%5)] = ''
    g = ggplot(data.frame(x = 1:10, y = (1:10)^2), aes(x,y)) +
      geom_point() +
      scale_y_continuous(breaks = seq(0,100,10), labels = labs) +
      theme(axis.ticks.length=unit(10, "pt"))
    
    gg = ggplotGrob(g)
    yaxis <- gg$grobs[[which(gg$layout$name == "axis-l")]]  
    ticks <- yaxis$children[[2]]
    marks = ticks$grobs[[2]]
    marks$x[c(2:5,7:10)*2-1] = unit(1, "npc") - unit(3, "pt")
    
    # Put the tick marks back into the plot
    ticks$grobs[[2]] = marks
    yaxis$children[[2]] = ticks
    gg$grobs[[which(gg$layout$name == "axis-l")]]  = yaxis
    grid.draw(gg)
    

    enter image description here