今天来教大家怎么在用使用ggplot2
画散点图的时候将坐标轴居中,即将两个坐标轴交叉位置设置为原点(0,0)。
1、需求描述
默认情况下,在使用ggplot2
画散点图时,x 坐标轴位于图片最底部,y 坐标轴位于图片最左边,比如我们生成一个示例数据来画散点图,代码如下:
library(ggplot2)
set.seed(6)# 设置随机种子,当随机种子固定后,生成的随机数将不会发生变化
dfdata.frame(x=rnorm(50),y=rnorm(50))
## 绘制 x 和 y 的散点图
ggplot(df, aes(x=x,y=y))+
geom_point()+
theme_classic()# 一种 ggplot2 主题,会仅显示坐标轴,并且不显示网格
上述代码所绘制的散点图如下所示:
从图中可以发现,x 和 y 坐标轴分别位于图片的最底部和最左边。
但是有时候我们想要将 x 和 y 坐标轴的交叉点放到(0, 0)的位置,这样可以更加清晰地分辨出四个象限,也会容易观察出数据的 pattern。
然而ggplot2
中并没有合适的函数可以实现这个需求,因此我们需要自定义函数来实现该功能。
2、需求实现
由于ggplot2
中的坐标轴本质上就是两条线,并且ggplot2
提供了函数(geom_line
)来绘制直线,也提供了函数(annotate
)在图中添加注释,因此我们可以借助这些函数来绘制坐标轴直线、坐标轴刻度和标签。
下面定义一个函数(theme_with_xy_centered
)来将 x 和 y 坐标轴居中(代码有些长,并添加了较为详细的注释):
theme_with_xy_centered xlimit, ylimit, xgeo = 0,
ygeo = 0, color = "black",
xlab = "x", ylab = "y",
num_ticks = 10, lab_textsize = 4,
tick_textsize = 3, linewidth = 1,
epsilon = max(xlimit,ylimit)/50) {
xaxis 2))
yaxis 2), y_ax = c(-ylimit, ylimit))
theme.list theme_void(), geom_line(aes(x = x_ax, y = y_ax), color = color, data = xaxis, linewidth=linewidth),
geom_line(aes(x = x_ax, y = y_ax), color = color, data = yaxis, linewidth=linewidth),
annotate("text", x = xlimit + 2*epsilon, y = ygeo, label = xlab, size = lab_textsize, vjust=-0.5, hjust=1),
annotate("text", x = xgeo, y = ylimit + 4*epsilon, label = ylab, size = lab_textsize, vjust=-0.3), xlim(-xlimit - 7*epsilon, xlimit + 7*epsilon),
ylim(-ylimit - 7*epsilon, ylimit + 7*epsilon) )
ticks_x q(-xlimit, xlimit, length.out = num_ticks), 2) ticks_y q(-ylimit, ylimit, length.out = num_ticks), 2)
nlist length(theme.list)
for (k in 1:num_ticks){
xtick 2), yt = c(xgeo + epsilon, xgeo))
ytick yt = rep(ticks_y[k], 2))
theme.list[[nlist + 4*k-3]] x = xt, y = yt),
data = xtick, color = color,
linewidth=linewidth)
theme.list[[nlist + 4*k-2]] "text",
x = ticks_x[k], y = ygeo - epsilon,
size = tick_textsize, vjust = 1,
label = paste(ticks_x[k]))
theme.list[[nlist + 4*k-1]] x = xt, y = yt),
data = ytick, color = color,
linewidth=linewidth)
theme.list[[nlist + 4*k]] "text",
x = xgeo - epsilon, y = ticks_y[k],
size = tick_textsize, hjust = 1,
label = paste(ticks_y[k])) }
return(theme.list)}
下面主要讲一下该函数的思路和功能,具体参数的含义请参考函数内部的注释。
该函数的主要思路是创建一个新的ggplot
主题(theme
),该主题实质上是R
语言中的列表(list
),而list
可以直接添加在ggplot
创建的图层中。
在创建该主题的list
时,首先使用了geom_line
和annotate
函数来创建 x 和 y 坐标轴及标签,然后计算需要在坐标轴上绘制的刻度的坐标,再采用循环的方式给坐标轴添加刻度及标签,在循环中仍然使用了geom_line
和annotate
这两个函数。
下面看一下使用了该函数以后的散点图,运行如下代码:
set.seed(6)# 设置随机种子,当随机种子固定后,生成的随机数将不会发生变化
dfdata.frame(x=rnorm(50),y=rnorm(50))
## 将 xy 轴居中,放到原点 (0,0) 上
xlimitmax(abs(df$x),abs(df$y))
ylimitxlimit
ggplot(df)+
geom_point(aes(x=x,y=y))+
theme_with_xy_centered(
xlimit=xlimit,ylimit=ylimit,
linewidth=0.4
)
绘制的散点图如下:
可以发现,此时 x 坐标轴与 y=0 直线重合了,而 y 坐标轴与 x=0 直线重合了,并且可以清晰地分辨出四个象限。
此外,theme_with_xy_centered
函数有很多参数可以设置,这里列举几个常用的参数,全部参数请查看该函数的源代码。
•xlimit
:坐标轴的范围,一般为绘图数据的最大值•ylimit
:坐标轴的范围,一般为绘图数据的最大值•color
:设置坐标轴颜色•xlab
:设置 x 坐标轴的标签,默认是 x•ylab
:设置 y 坐标轴的标签,默认是 y•num_ticks
:在每个坐标轴上添加的刻度数目,默认是 10 个刻度
3、本文参考链接
https://stackoverflow.com/questions/17753101/center-x-and-y-axis-with-ggplot2
高颜值免费 SCI 在线绘图(点击图片直达)
最全植物基因组数据库IMP (点击图片直达)
往期精品(点击图片直达文字对应教程)
机器学习