前天的推文里模仿論文中的散點圖以原點為中心花了一個坐標軸,R語言的ggplot2畫圖通常坐標軸是在左下角,如果想把坐標軸改成以原點(0,0)為中心應該如何實現呢?經過搜索找到了一些辦法,記錄在這篇推文里。
參考的鏈接是https://stackoverflow.com/questions/17753101/center-x-and-y-axis-with-ggplot2
第一步需要確定數據的范圍,比如用鳶尾花的數據集花瓣長寬分別做x和y
用summary()
函數看一下數據的范圍
image.png
最大值是6.9,那我們將坐標軸的范圍設置為-7~7.
axis_begin<- -7
axis_end<-7
刻度設置為15個
total_ticks<-15
最終是通過
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
首先是基本的散點圖
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
添加坐標軸的線和刻度以及文字標簽
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))
最終的效果如下
image.png
在前天的推文下有人留言直接把以上代碼打包成了函數
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)}
畫圖的時候直接用如下代碼
draw_axis_line(20, 4)
20是x軸的范圍,4是y軸的范圍
最終的出圖效果
image.png
在文章開頭提到的參考鏈接里,有人還提供了一個主題函數
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)
}
畫圖代碼
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")
最終效果如下
image.png
歡迎大家關注我的公眾號
小明的數據分析筆記本留言討論