前天的推文里跟着Nature microbiology学画图~ggplot2散点图添加分组边界模仿论文中的散点图以原点为中心花了一个坐标轴,R语言的ggplot2画图通常坐标轴是在左下角,如果想把坐标轴改成以原点(0,0)为中心应该如何实现呢?经过搜索找到了一些办法,记录在这篇推文里。
参考的链接是
https://stackoverflow.com/questions/17753101/center-x-and-y-axis-with-ggplot2
第一步需要确定数据的范围,比如用鸢尾花的数据集花瓣长宽分别做x和y
用summary()
函数看一下数据的范围
summary(iris)
最大值是6.9,那我们将坐标轴的范围设置为-7~7.
代码语言:javascript复制axis_begin<- -7
axis_end<-7
刻度设置为15个
代码语言:javascript复制total_ticks<-15
代码语言:javascript复制最终是通过
geom_segment()
函数来画坐标轴,所以需要先构造画图的数据
library(magrittr)#这个包里有管道符
tick_frame<-data.frame(ticks=seq(axis_begin,
axis_end,
length.out = total_ticks),
zero=0)%>%
subset(ticks != 0)
tick_frame
label_frame<-data.frame(lab=seq(axis_begin,axis_end),
zero=0)%>%
subset(lab!=0&abs(lab)!=7)
label_frame
首先是基本的散点图
代码语言:javascript复制ggplot(iris,aes(x=Petal.Length,y=Petal.Width))
geom_point(color="red",size=3)
image.png
接下来简单修饰
包括
- 去灰色背景
- 更改坐标轴范围
- 添加最外圈的方框
- 去掉最外圈的文字和小短线
ggplot(iris,aes(x=Petal.Length,y=Petal.Width))
geom_point(color="red",size=3)
theme_bw()
scale_x_continuous(limits = c(-7,7))
scale_y_continuous(limits = c(-7,7))
theme(panel.grid = element_blank(),
axis.text = element_blank(),
axis.ticks = element_blank())
image.png
添加坐标轴的线和刻度以及文字标签
代码语言:javascript复制ggplot(iris,aes(x=Petal.Length,y=Petal.Width))
geom_point(color="red",size=3)
theme_bw()
theme(panel.grid = element_blank(),
axis.text = element_blank(),
axis.ticks = element_blank())
geom_segment(x=0,xend=0,y=-7,yend=7)
geom_segment(x=-7,xend=7,y=0,yend=0)
scale_x_continuous(expand = c(0,0),limits = c(-7,7))
scale_y_continuous(expand = c(0,0),limits = c(-7,7))
geom_segment(data=tick_frame,aes(x=zero,xend=zero 0.1,
y=ticks,yend=ticks))
geom_segment(data=tick_frame,aes(x=ticks,xend=ticks,
y=zero,yend=zero 0.1))
geom_text(data=label_frame,aes(x=zero-0.2,y=lab,label=lab))
geom_text(data=label_frame,aes(x=lab,y=zero-0.2,label=lab))
最终的效果如下
在前天的推文下跟着Nature microbiology学画图~ggplot2散点图添加分组边界有人留言直接把以上代码打包成了函数
代码语言:javascript复制draw_axis_line <- function(length_x,length_y,tick_step=NULL,lab_step=NULL){
axis_x_begin <- -1 * length_x
axis_x_end <- length_x
axis_y_begin <- -1 * length_y
axis_y_end <- length_y
if (missing(tick_step))
tick_step <- 1
if (is.null(lab_step))
lab_step <- 2 #axis ticks data
tick_x_frame <- data.frame(ticks=seq(axis_x_begin,axis_x_end,by=tick_step))
tick_y_frame <- data.frame(ticks=seq(axis_y_begin,axis_y_end,by=tick_step)) #axis labels data
lab_x_frame <- subset(data.frame(lab=seq(axis_x_begin,axis_x_end,by=lab_step),zero=0),lab!=0)
lab_y_frame <- subset(data.frame(lab=seq(axis_y_begin,axis_y_end,by=lab_step),zero=0),lab!=0) #set tick length
tick_x_length <- 15/length(tick_x_frame$ticks)/2
tick_y_length <- 8/length(tick_y_frame$ticks)/2 #set zero point
data <- data.frame(x=0,y=0)
library(ggplot2)
p <- ggplot(data=data) #draw axis line
geom_segment(y=0,yend=0,x=axis_x_begin,xend=axis_x_end,size=0.5)
geom_segment(x=0,xend=0,y=axis_y_begin,yend=axis_y_end,size=0.5) #draw x ticks
geom_segment(data=tick_x_frame,aes(x=ticks,xend=ticks,y=0,yend=0 tick_x_length)) #draw y ticks
geom_segment(data=tick_y_frame,aes(x=0,xend=0 tick_y_length,y=ticks,yend=ticks)) #labels
geom_text(data=lab_x_frame,aes(x=lab,y=zero,label=lab),vjust=1.5)
geom_text(data=lab_y_frame,aes(x=zero,y=lab,label=lab),hjust=1.5)
theme_void()
return(p)}
画图的时候直接用如下代码
代码语言:javascript复制draw_axis_line(20, 4)
20是x轴的范围,4是y轴的范围
最终的出图效果
image.png
在文章开头提到的参考链接里,有人还提供了一个主题函数
代码语言:javascript复制theme_geometry <- function(xvals, yvals, xgeo = 0, ygeo = 0,
color = "black", size = 1,
xlab = "x", ylab = "y",
ticks = 10,
textsize = 3,
xlimit = max(abs(xvals),abs(yvals)),
ylimit = max(abs(yvals),abs(xvals)),
epsilon = max(xlimit,ylimit)/50){
#INPUT:
#xvals .- Values of x that will be plotted
#yvals .- Values of y that will be plotted
#xgeo .- x intercept value for y axis
#ygeo .- y intercept value for x axis
#color .- Default color for axis
#size .- Line size for axis
#xlab .- Label for x axis
#ylab .- Label for y axis
#ticks .- Number of ticks to add to plot in each axis
#textsize .- Size of text for ticks
#xlimit .- Limit value for x axis
#ylimit .- Limit value for y axis
#epsilon .- Parameter for small space
#Create axis
xaxis <- data.frame(x_ax = c(-xlimit, xlimit), y_ax = rep(ygeo,2))
yaxis <- data.frame(x_ax = rep(xgeo, 2), y_ax = c(-ylimit, ylimit))
#Add axis
theme.list <-
list(
theme_void(), #Empty the current theme
geom_line(aes(x = x_ax, y = y_ax), color = color, size = size, data = xaxis),
geom_line(aes(x = x_ax, y = y_ax), color = color, size = size, data = yaxis),
annotate("text", x = xlimit 2*epsilon, y = ygeo, label = xlab, size = 2*textsize),
annotate("text", x = xgeo, y = ylimit 4*epsilon, label = ylab, size = 2*textsize),
xlim(-xlimit - 7*epsilon, xlimit 7*epsilon), #Add limits to make it square
ylim(-ylimit - 7*epsilon, ylimit 7*epsilon) #Add limits to make it square
)
#Add ticks programatically
ticks_x <- round(seq(-xlimit, xlimit, length.out = ticks),2)
ticks_y <- round(seq(-ylimit, ylimit, length.out = ticks),2)
#Add ticks of x axis
nlist <- length(theme.list)
for (k in 1:ticks){
#Create data frame for ticks in x axis
xtick <- data.frame(xt = rep(ticks_x[k], 2),
yt = c(xgeo epsilon, xgeo - epsilon))
#Create data frame for ticks in y axis
ytick <- data.frame(xt = c(ygeo epsilon, ygeo - epsilon),
yt = rep(ticks_y[k], 2))
#Add ticks to geom line for x axis
theme.list[[nlist 4*k-3]] <- geom_line(aes(x = xt, y = yt),
data = xtick, size = size,
color = color)
#Add labels to the x-ticks
theme.list[[nlist 4*k-2]] <- annotate("text",
x = ticks_x[k],
y = ygeo - 2.5*epsilon,
size = textsize,
label = paste(ticks_x[k]))
#Add ticks to geom line for y axis
theme.list[[nlist 4*k-1]] <- geom_line(aes(x = xt, y = yt),
data = ytick, size = size,
color = color)
#Add labels to the y-ticks
theme.list[[nlist 4*k]] <- annotate("text",
x = xgeo - 2.5*epsilon,
y = ticks_y[k],
size = textsize,
label = paste(ticks_y[k]))
}
#Add theme
#theme.list[[3]] <-
return(theme.list)
}
画图代码
代码语言:javascript复制simdata <- data.frame(x = rnorm(50), y = rnorm(50))
ggplot(simdata)
theme_geometry(simdata$x, simdata$y)
geom_point(aes(x = x, y = y), size = 3, color = "red")
ggtitle("More geometric example")
最终效果如下