Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ggplot2: Have shorter tick marks for tick marks without labels

Tags:

r

ggplot2

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.

like image 934
baisong Avatar asked Jan 08 '15 21:01

baisong


2 Answers

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

like image 184
jbaums Avatar answered Nov 16 '22 15:11

jbaums


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

like image 23
Sandy Muspratt Avatar answered Nov 16 '22 15:11

Sandy Muspratt