ggplot轴位置和次刻度

时间:2019-09-23 10:42:36

标签: r ggplot2

我正在运行以下代码:

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

在x轴上很完美,但我收到以下消息:

  

警告信息:   在split.default(as.integer(seq_along(x $ x)),id)中:   数据长度不是分割变量的倍数

我将y轴放置在正确的位置,但是次刻度线仅出现在我犯错的第一个到主要刻度线之间?

2 个答案:

答案 0 :(得分:0)

我对您的代码了解得很少,但我想我已经确定了这个地方 你的问题在哪里。它在您的shift_yaxis函数中。在尝试调试时,我用#阻止了以下几行:

# 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)))  

然后,我得到了正确的图形。

否则,我使用了您的原始代码。因此,如果在上一行添加#,则可以忽略以下内容。

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

答案 1 :(得分:0)

修复它:

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