锹形虫

V1

2023/02/05阅读:38主题:嫩青

画一个坐标轴

“移动” ggplot2 的坐标轴

我想画一个当 y 轴存在正负值的时候,x 轴能在 y = 0 处,而不是在 y 的最小值处。

1. 目标

最开始画这个图的时候,也刚开始接触ggplot2,凭仅有的知识没能调整 x 轴到 y = 0 处,于是就查了一些资料,发现不管是 R studio 还是 stackflow 上都提示使用 ggplot2 并不好解决这个问题。但我还是想画出这个图,所以终于在多次调试和修改之后,大致达到了目标图形的效果。

简单来说就是隐藏原来的坐标轴,重新绘制坐标轴及刻度线。这个过程加强了我对 ggplot2 的练习。

2. 实现

我将这个绘制过程打包成了一个函数,因为设置的参数比较多,所以额外定义了一个数据框axisparameters来方便输入参数,数据框第一列就是参数名。另外我在函数中也注释了每个参数的作用。但需要注意的是,上图目标中的轴线其实是被掩盖在散点后方的(猜测作者的绘制方法可能也与下述方法差异不大),这是因为受限于 ggplot2 的图层概念。

【1】我认为这有碍美观,因此我建议在使用这个函数时,直接复制到脚本中再次定义它,并在函数中在坐标轴被绘制之前,指定需要绘制的额外图像(例如散点图,线图等),这就能让我们绘制的坐标轴不被遮盖住。

【2】可能是因为输入数据量纲差异的原因,新绘制的 x 轴和 y 轴的刻度长短会受到影响,因此我建议多次调试这两个参数,以达到较为美观的刻度大小。

【3】函数将返回隐藏原 x 轴和 y 轴信息的 ggplot 绘图对象,我设定了默认的主题为theme_classic(),因此需要使用其他主题时仍然需要重新定义函数,这在函数代码中已标注。

【4】我设定了默认的刻度值字体为Times New Roman,可以重新定义函数时重新设置。lb_font_size参数为坐标轴刻度值的字体大小。

【5】另外需要注意的是,传入的用于 aes 的 x 和 y 需要是对象的形式,因此参数的传入方式应该是moveaxisfunc(axisparameters, 5, data, data$varX, data$varY),请保存函数返回对象,并直接使用+继续美化图像。

3. 代码

以下是实现代码,因为我仍然在努力学习的路上,代码中有错误或者不够精炼的地方大家可自己作更多完善。若不嫌麻烦甚至可将优化后的代码直接发到本号的后台,感谢,让开源精神在这个社区流动。

# 请在标注区绘图
# 定义坐标轴所需参数的数据框,axisparametes,并传入了一些示例参数
axisparameters <- data.frame(parameter = c('begin','end','ticks_num','sep','axis_position''ticks_sz'),
x_axis = c('','','','','',''),
y_axis = c('','','','','',''))
# axisparameters setting: 
#       parameter x_axis y_axis
# 1         begin   15.0   -4.0# 分别对应两个坐标轴的起点值
# 2           end  100.0    4.0# 分别对应两个坐标轴的终点值
# 3     ticks_num   10.0    5.0# 分别对应两个坐标轴的刻度数量
# 4           sep   10.0    2.0# 分别对应两个坐标轴的步进,也就是有值的刻度之间的间隔
# 5 axis_position    0.0   15.0# 分别对应两个坐标轴的未知
# 6      ticks_sz    0.1    0.5# 分别对应两个坐标轴的刻度齿长度
axisparameters$x_axis <- c(15,100,10,10,0,0.1)
axisparameters$y_axis <- c(-4,4,5,2,15,0.5)
# 定义坐标轴绘制函数,需要传入 axisparameters, 刻度值的字体大小, 用于 ggplot 的 data 和用于 aes 的 x 和 y
moveaxisfunc <- function(axisparameters,lb_font_size,data, x, y)
{
  # 传参数
  xaxis_begin  <- axisparameters[1,2]
  xaxis_end    <- axisparameters[2,2]
  xtotal_ticks <- axisparameters[3,2]
  x_sep <- axisparameters[4,2]
  x_loc <- axisparameters[5,2]
  x_ticks_sz <- axisparameters[6,2]
  yaxis_begin  <- axisparameters[1,3]
  yaxis_end    <- axisparameters[2,3]
  ytotal_ticks <- axisparameters[3,3]
  y_sep <- axisparameters[4,3]
  y_loc <- axisparameters[5,3]
  y_ticks_sz <- axisparameters[6,3]
  # 计算绘制 x 轴所需的数据
  xtick_frame <- 
    data.frame(ticks = seq(xaxis_begin, xaxis_end, x_sep), 
               zero=0) %>%
    subset(ticks != 0)
  xlab_frame <- data.frame(lab = seq(xaxis_begin, xaxis_end, x_sep),
                           zero = 0) %>%
    subset(lab != 0)
  xtick_sz <- (tail(xlab_frame$lab, 1) -  xlab_frame$lab[1]) / 128
  # 计算绘制 y 轴所需的数据
  ytick_frame <-
    data.frame(ticks = seq(yaxis_begin, yaxis_end, y_sep),
               zero=0) %>%
    subset(ticks != 0)
  ylab_frame <- data.frame(lab = seq(yaxis_begin, yaxis_end, y_sep),
                           zero = 0) %>%
    subset(lab != 0)
  ytick_sz <- (tail(ylab_frame$lab, 1) -  ylab_frame$lab[1]) / 128
  # 绘图
  plot1 <- ggplot(data, aes(x, y)) +
    ############################################################请在这里绘制额外图形
    geom_point+
    
    
    
    
    #############################################################
    # y 轴
    geom_segment(x = y_loc, xend = y_loc,
                 y = ylab_frame$lab[1], yend = tail(ylab_frame$lab, 1),
                 size = 1) +
    # y 轴刻度
    geom_segment(data = ytick_frame,
                 aes(x = y_loc, xend = y_loc + y_ticks_sz,
                     y = ticks, yend = ticks),size = 1) +
    # x 轴
    geom_segment(y = x_loc, yend = x_loc, 
                 x = xaxis_begin, xend = tail(xlab_frame$lab, 1),
                 size = 1) +
    # x 轴刻度
    geom_segment(data = xtick_frame, 
                 aes(x = ticks, xend = ticks, 
                     y = zero, yend = x_ticks_sz), size = 1) +
    # 此处默认的字体为“Times New Roman”,如有需要可额外修改
    # x 轴刻度值
    geom_text(data=xlab_frame, aes(x=lab, y=zero, label=lab),
              family = 'Times New Roman', vjust=1.5, size = lb_font_size) +
    # y 轴刻度值
    geom_text(data=ylab_frame, aes(x=y_loc -1, y=lab, label=lab),
              family = 'Times New Roman', hjust=1.5,size = lb_font_size) +
    # 隐藏原来坐标轴信息
    theme_classic()+
    theme(axis.text.x = element_blank(), 
          axis.ticks.x = element_blank(),
          axis.line.x = element_blank(),
          axis.ticks.y = element_blank(),
          axis.line.y = element_blank(),
          axis.text.y = element_blank())
  return(plot1)
}
moveaxisfunc(axisparameters, 5, data, data$varX, data$varY)
save(axisparameters,moveaxisfunc, file = 'code/moveaxisfunc.Rdata'

以上就是本次分享的内容啦。在不断练习的过程中也是在不断学习和交流。R 社区的开源精神流转地很好,下次再有觉得还不错的函数定义,我再分享哦~ 加油加油!下面是一些参考资料来源,回见!

Stackflow[1] R Studio[2] tutorialspoint[3]

参考资料

[1]

Stackflow: https://stackoverflow.com/questions/17753101/center-x-and-y-axis-with-ggplot2/49202967#49202967

[2]

R Studio: https://community.rstudio.com/t/i-cannot-move-my-x-axis-to-the-y-0-help/112773/2

[3]

tutorialspoint: https://www.tutorialspoint.com/how-to-change-the-position-of-x-axis-in-base-r-plot

分类:

其他

标签:

医学

作者介绍

锹形虫
V1