0

I'm running the following code:

library(ggplot2)
library(grid)

df <- data.frame(x = -10:10, y = -10:10)

# 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, y = round(n_minor),function(x, y) c(x, rep("", y) )))
  labs[1:(length(labs) - n_minor)]
}

shift_yaxis <- function(p, x=0){
  g <- ggplotGrob(p)

  dummy <- data.frame(x=x)
  yaxis <- g[["grobs"]][g$layout$name == "axis-l"][[1]]

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

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

  # Edit the x 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(12, "pt"), unit(1, "npc"),   
                          rep(unit.c(unit(1, "npc") - unit(3, "pt"), unit(1, "npc")), y_n_minor)))

  # Put the tick marks back into the plot
  ticks$grobs[[2]] = marks
  yaxis$children[[2]] = ticks

  p + annotation_custom(grid::grobTree(yaxis, vp = grid::viewport(x=1, height=sum(yaxis$height))),xmax=x, xmin=x) +
    geom_vline(aes(xintercept=x), data = dummy) +
    theme(axis.text.y = element_blank(), 
          axis.ticks.y=element_blank())

}

shift_xaxis <- function(p, y=0){
  g <- ggplotGrob(p)

  dummy <- data.frame(y=y)
  xaxis <- g[["grobs"]][g$layout$name == "axis-b"][[1]]

  # 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")), x_n_minor)))

  # Put the tick marks back into the plot
  ticks$grobs[[1]] = marks
  xaxis$children[[2]] = ticks

  p + annotation_custom(grid::grobTree(xaxis, vp = grid::viewport(y=1, height=sum(xaxis$height))), 
                        ymax=y, ymin=y) +
    geom_hline(aes(yintercept=y), data = dummy) +
    theme(axis.text.x = element_blank(), axis.ticks.x=element_blank())  
}

# Range of x values, Major tick marks, Minor tick marks
range_x = -20:20
major_x = 2
minor_x = 0.2

x_seq_major=seq(min(range_x), max(range_x),major_x)
x_n_minor = major_x/minor_x - 1

# Range of y values, Major tick marks, Minor tick marks
range_y = -10:10
major_y = 2
minor_y = 0.2

y_seq_major=seq(min(range_y), max(range_y),major_y)
y_n_minor = major_y/minor_y - 1

# Getting the  x 'breaks' and 'labels' for the ggplot
breaks_x = seq(min(range_x), max(range_x), minor_x)
labels_x = insert_minor(x_seq_major, x_n_minor)
if(length(breaks_x) > length(labels_x)) labels_x = c(labels_x, rep("", length(breaks_x) - length(labels_x)))

# Getting the  y 'breaks' and 'labels' for the ggplot
breaks_y = seq(min(range_y), max(range_y), minor_y)
labels_y = insert_minor(y_seq_major, y_n_minor)
if(length(breaks_y) > length(labels_y)) labels_y = c(labels_y, rep("", length(breaks_y) - length(labels_y)))

# The plot
p <- ggplot(df, aes(x = x, y = y)) + 
  geom_point() + scale_x_continuous(breaks=breaks_x,labels=labels_x) +
  scale_y_continuous(breaks = breaks_y, labels = labels_y) +
  coord_cartesian(xlim=range_x) +
  theme_bw() +  
  theme(panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        panel.border = element_blank(),
        axis.text.x=element_text(margin=margin(t=0.2, unit="cm")))
p

# Draw the plot
#grid.newpage()
f <- shift_yaxis(p,0)
f <- shift_xaxis(f,0)
f

It is perfect on x axis but i receive the following message:

Warning message: In split.default(as.integer(seq_along(x$x)), id) : data length is not a multiple of split variable

and I get y axis in the right position but minor tick are present only between the first to major tick, where I'm make mistake?

kath
  • 7,624
  • 17
  • 32

2 Answers2

0

I know very little about your code, but I think I have identified the place where your problem is. It is within your shift_yaxis function. While I was trying to debug, I blocked the following lines with #:

# marks$x = unit.c(unit.c(unit(1, "npc") - unit(12, "pt"), unit(1, "npc"),   
#         rep(unit.c(unit(1, "npc") - unit(3, "pt"), unit(1, "npc")), y_n_minor)))  

Then, I got the correct graph.

Otherwise, I used your original code. So you can ignore the following if you add # in the above line.

library(ggplot2)
library(grid)
df <- data.frame(x = -10:10, y = -10:10)
# 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, y = round(n_minor),function(x, y) c(x, rep("", y) )))
  labs[1:(length(labs) - n_minor)]
}
shift_yaxis <- function(p, x=0){
  g <- ggplotGrob(p)
  dummy <- data.frame(x=x)
  yaxis <- g[["grobs"]][g$layout$name == "axis-l"][[1]]
   # Get the tick marks and tick mark labels   
  ticks <- yaxis$children[[2]]
   # Get the tick marks
  marks = ticks$grobs[[2]]
  # Edit the x 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(12, "pt"), unit(1, "npc"),   
  #                        rep(unit.c(unit(1, "npc") - unit(3, "pt"), unit(1, "npc")), y_n_minor)))

  # Put the tick marks back into the plot
  ticks$grobs[[2]] = marks
  yaxis$children[[2]] = ticks
  p + annotation_custom(grid::grobTree(yaxis, vp = grid::viewport(x=1,   height=sum(yaxis$height))),xmax=x, xmin=x) +
    geom_vline(aes(xintercept=x), data = dummy) +
    theme(axis.text.y = element_blank(), 
          axis.ticks.y=element_blank())
}
shift_xaxis <- function(p, y=0){
  g <- ggplotGrob(p)
  dummy <- data.frame(y=y)
  xaxis <- g[["grobs"]][g$layout$name == "axis-b"][[1]]
# 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")), x_n_minor)))

  # Put the tick marks back into the plot
  ticks$grobs[[1]] = marks
  xaxis$children[[2]] = ticks

  p + annotation_custom(grid::grobTree(xaxis, vp = grid::viewport(y=1, height=sum(xaxis$height))), 
                    ymax=y, ymin=y) +
    geom_hline(aes(yintercept=y), data = dummy) +
    theme(axis.text.x = element_blank(), axis.ticks.x=element_blank())  
}

# Range of x values, Major tick marks, Minor tick marks
range_x = -20:20
major_x = 2
minor_x = 0.2

x_seq_major=seq(min(range_x), max(range_x),major_x)
x_n_minor = major_x/minor_x - 1

# Range of y values, Major tick marks, Minor tick marks
range_y = -10:10
major_y = 2
minor_y = 0.2

y_seq_major=seq(min(range_y), max(range_y),major_y)
y_n_minor = major_y/minor_y - 1

# Getting the  x 'breaks' and 'labels' for the ggplot
breaks_x = seq(min(range_x), max(range_x), minor_x)
labels_x = insert_minor(x_seq_major, x_n_minor)
if(length(breaks_x) > length(labels_x)) labels_x = c(labels_x, rep("", length(breaks_x) - length(labels_x)))

# Getting the  y 'breaks' and 'labels' for the ggplot
breaks_y = seq(min(range_y), max(range_y), minor_y)
labels_y = insert_minor(y_seq_major, y_n_minor)
if(length(breaks_y) > length(labels_y)) labels_y = c(labels_y, rep("", length(breaks_y) - length(labels_y)))

# The plot
p <- ggplot(df, aes(x = x, y = y)) + 
  geom_point() + scale_x_continuous(breaks=breaks_x,labels=labels_x) +
  scale_y_continuous(breaks = breaks_y, labels = labels_y) +
  coord_cartesian(xlim=range_x) +
  theme_bw() +  
  theme(panel.grid.major = element_blank(),
       panel.grid.minor = element_blank(),
       panel.border = element_blank(),
        axis.text.x=element_text(margin=margin(t=0.2, unit="cm")))
p 

f <- shift_yaxis(p, 0)
f <- shift_xaxis(f,0)
f

enter image description here

Zhiqiang Wang
  • 6,206
  • 2
  • 13
  • 27
  • Thanks for your answer, I see the problem is in the line of code you blocked, but removing this line major tick are of the same length of minor tick, it is clear where is the problem, but is not cleat to me because the same line of code is perfect for shift_xaxis – ANTONIO VIVI Sep 24 '19 at 07:36
0

fix it:

library(ggplot2)
library(grid)

df<-data.frame(x=-10:10,y=-10:10)

# 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, y = round(n_minor),function(x, y) c(x, rep("", y) )))
    labs[1:(length(labs) - n_minor)]
}

shift_yaxis <- function(p, x=0){
    g <- ggplotGrob(p)

    dummy <- data.frame(x=x)
    yaxis <- g[["grobs"]][g$layout$name == "axis-l"][[1]]

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

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

    # Edit the x 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")), y_n_minor)))

    marks$x =unit.c(rep(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")), y_n_minor))),length(y_seq_major)-1),
           unit.c(unit(1, "npc") - unit(6, "pt"), unit(1, "npc")))

    # Put the tick marks back into the plot
    ticks$grobs[[2]] = marks
    yaxis$children[[2]] = ticks

    p + annotation_custom(grid::grobTree(yaxis, vp = grid::viewport(x=1, height=sum(yaxis$height))), 
                         xmax=x, xmin=x) +
        geom_vline(aes(xintercept=x), data = dummy) +
        theme(axis.text.y = element_blank(), 
              axis.ticks.y=element_blank())

}

shift_xaxis <- function(p, y=0){
    g <- ggplotGrob(p)

    dummy <- data.frame(y=y)
    xaxis <- g[["grobs"]][g$layout$name == "axis-b"][[1]]

    # 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")), x_n_minor)))

    # Put the tick marks back into the plot
    ticks$grobs[[1]] = marks
    xaxis$children[[2]] = ticks

    p + annotation_custom(grid::grobTree(xaxis, vp = grid::viewport(y=1, height=sum(xaxis$height))), 
                          ymax=y, ymin=y) +
        geom_hline(aes(yintercept=y), data = dummy) +
        theme(axis.text.x = element_blank(), axis.ticks.x=element_blank())

}

# Range of x values, Major tick marks, Minor tick marks
range_x = -20:20
major_x = 2
minor_x = 0.2

x_seq_major=seq(min(range_x), max(range_x),major_x)
x_n_minor = major_x/minor_x - 1

# Range of y values, Major tick marks, Minor tick marks
range_y = -20:20
major_y = 2
minor_y = 0.2

y_seq_major=seq(min(range_y), max(range_y),major_y)
y_n_minor = major_y/minor_y - 1

# Getting the  x 'breaks' and 'labels' for the ggplot

breaks_x = seq(min(range_x), max(range_x), minor_x)
labels_x = insert_minor(x_seq_major, x_n_minor)
if(length(breaks_x) > length(labels_x)) labels_x = c(labels_x, rep("", length(breaks_x) - length(labels_x)))

# Getting the  y 'breaks' and 'labels' for the ggplot

breaks_y = seq(min(range_y), max(range_y), minor_y)
labels_y = insert_minor(y_seq_major, y_n_minor)
if(length(breaks_y) > length(labels_y)) labels_y = c(labels_y, rep("", length(breaks_y) - length(labels_y)))




# The plot
p <- ggplot(df, aes(x = x, y = y)) + 
     geom_point() +
     scale_x_continuous(breaks=breaks_x,labels=labels_x) +
     scale_y_continuous(breaks=breaks_y,labels=labels_y) +
     coord_cartesian(xlim=range_x,ylim = range_y) + 
     theme_bw() +  
     theme(panel.grid.major = element_blank(),
           panel.grid.minor = element_blank(),
           panel.border = element_blank(),
           axis.text.x=element_text(margin=margin(t=0.2, unit="cm")),
           axis.text.y=element_text(margin=margin(r=0.2, unit="cm")))
p

# Draw the plot
#grid.newpage()
f <- shift_yaxis(p,0)
f <- shift_xaxis(f,0)
f