R語言--同一圖片中繪制兩種比例的曲線


 今天有同學問怎樣用R繪制右邊這樣一張圖片。一看這不就是雙坐標軸么,簡單啊,雖然現在用R比較少,直接上手代碼有點羞澀,但還是知道在哪能夠找到資源的。為此打開R語言實戰這本寶典,想要繪制雙坐標軸。
書上繪制的樣子是如右圖這樣的,代碼如下:

x=c(1:10)

y=x

z=10/x

opar=par(no.readonly=TRUE)

par(mar=c(5,4,4,8),0.1)

plot(x,y,type="b",pch=21,col="red",yaxt="n",lty=3,ann=FALSE)

lines(x,z,type="b",pch=22,col="blue",lty=2)

axis(2,at=x,labels=x,col.axis="red",las=2)

axis(4,at=z,labels=round(z,digits=2),col.axis="blue",las=2,cex.lab=0.7,tck=-0.008)

mtext("y=1/x",side=4,line=3,cex.lab=1,las=0,col="blue")

title("An Example of Creative Axes",xlab="X Values",ylab="Y=X")

par(opar)

此時縱軸的量級是一樣的,我的圖片是想要左右量級不同時,也能在一張圖里展示。

 

 

 為此,將z=1/x,帶入,由於z值范圍在0-1之間,所以展示出來的樣子如下,只能看到一個z值。這不行啊,不是我的目標啊。
 

思來想去,是不是我沒限定左右兩個坐標軸的范圍呢,試試吧:

x=c(1:10);

y=x;

z=1/x;

opar=par(no.readonly=TRUE)

par(mar=c(5,4,4,8),0.1)

plot(x,y,ylim=c(0,10),type="b",pch=21,col="red",yaxt="n",lty=3,ann=FALSE)

lines(x,z,ylim=c(0,1),type="b",pch=22,col="blue",lty=0,ann=FALSE)## ylim=c(0,1)限定z值的范圍。

axis(2,at=x,labels=x,col.axis="red",las=0)

axis(4,at=c(z[1],'','','','','','','','',z[10]),labels=round(z,digits=2),col.axis="blue",las=2,cex.lab=0.7,tck=-0.008)

##由於z之太密集,為展示好看,令c(z[1],'','','','','','','','',z[10])只顯示兩個值。

mtext("y=1/x",side=4,line=3,cex.lab=1,las=0,col="blue")

title("An Example of Creative Axes",xlab="X Values",ylab="Y=X")

par(opar)

展示圖片如下

 

但是這個樣子還是不是我想要的。搜羅腦海中關於繪制圖片的R代碼,但是沒想到什么好的辦法來解決。正當絞盡腦汁的時候,看到一個指導。立馬來試一下。

原文介紹是這樣:大家在使用R繪圖的時候,經常使用屬性不同的點或線來展示數據信息,這種數據展示方法貫穿了整個ggplot2系列。使用這種方法時,如果不同指標之間量級相差很大,就會泯滅量級較小指標的的變化,如下圖所示,指標2和指標3幾乎成了一條直線,這幅圖顯然不能充分展示數據信息。

dtf = data.frame(RMB=seq(7000,3400,-200),

指標1=c(200,400,450,500,300,100,400,700,830,1200,400,350,200,700,370,800,200,100,120),

指標2=c(2,5,8,3,2,2,4,7,9,4,4,2,2,7,5,12,5,4,4),

指標3=c(1.2,1.3,1.2,0.9,2.1,1.4,2.9,3.4,2.1,1.1,1.2,1.5,1.2,0.9,0.5,3.3,2.2,1.1,1.2))

library(tidyverse);

library(reshape2)

dtf%>%melt(id='RMB')%>%ggplot(aes(RMB,value,group=variable))+geom_line(aes(linetype=variable))+theme_classic();  展示如下

 

今天給大家介紹一種稍微不同的數據展示方法,在同一張圖中使用自由度不同的y軸來展示數據的不同屬性,這種方法可以很好地解決指標量級不同下數據展示問題。

推薦大家使用R基礎繪圖系統繪制這種多重坐標圖,不建議大家使用ggplot2繪圖系統。因為ggplot2的所有工作都是在唯一的坐標系中進行的,如果你分別繪制不同量級的指標,就意味着坐標系統發生變化,必然導致繪圖失敗。但也不能說ggplot2不畫這種圖,只是過程會非常艱辛。Hradly大神也不願看到你那么辛苦地畫了一個十分拙略的圖,他可能會推薦你使用分面的方式展示數據,但分面不是今天的主題。

繪圖策略:首先繪制一張圖片,然后在第一張圖片上繪其他圖片,最后手動添加坐標及圖例。過程非常簡單明了,但其中一些細節大家要注意。在繪制第一張圖時,若繪制雙Y軸要在圖片的右邊留足位置用來添加坐標,若繪制多Y軸坐標要在坐標留出至少10行的距離,右邊盡可能少留空間,若圖像允許可以把右邊留白設為0;第一張圖繪制成功后要調用par(new=T)函數,保證第二張圖是繪制在第一張圖的基礎上,第二張圖繪制成功后,調用aixs繪制坐標刻度,mtext添加坐標標簽。最后使用legend添加圖例,建議大家使用bty='n'去掉圖例的邊框,使用cex=0.85對字體進行放縮。

 

另外如果只想繪制雙Y坐標軸,可以使用plotrix包中的twoord.plot和twoord.stackplot,兩者稍有區別,前者使用不同Y軸相同的X軸,后者在同一張圖上使用不同的坐標系。還有lattice包中的doubleYScale函數,Plotly直接在add_lines函數中聲明要繪制雙Y軸即可,highcharter中通過hc_add_series直接添加不同尺度的Y軸。

這才是想要的樣子么。這樣的圖是怎么繪制呢?別急,代碼來了,

雙重坐標軸:

op=par(mar = c(5,5,2,5),cex.axis=0.6,cex.lab=0.75)

with(dtf, plot(RMB, 指標1, type="l", col="gray10", ylab='指標1',ylim=c(0,1300)))

par(new = T)

with(dtf, plot(RMB, 指標2, type="l", axes=F, xlab=NA, ylab=NA,lty=2,col="gray30"))

axis(side = 4)

mtext(side = 4, line = 3, '指標2',cex=0.75)

legend("topright",cex = 0.75,legend=c('指標1', '指標2'),bty = 'n',lty=c(1,2), col=c("gray10", "gray30"))

title(main = 'base:雙重坐標軸',cex=0.8,font=1)

par(op)

三重坐標軸:

attach(dtf)

op=par(mar=c(4, 11, 2, 1) + 0.1,cex.axis=0.75)

plot(RMB, 指標1, axes=F, ylim=c(0,max(指標1)), xlab='', ylab='',type='l',col='black', main='',xlim=c(7000,3400))

axis(2, ylim=c(0,max(指標1)),col='black',lwd=2)

mtext(2,text='指標1',line=2,cex = 0.75)

par(new=T)

plot(RMB, 指標2, axes=F, ylim=c(0,max(指標2)), xlab='', lty=2,ylab='',type='l',col='black', main='',xlim=c(7000,3400))

axis(2, ylim=c(0,max(指標2)),col='black',lwd=2,line=3.5)

mtext(2,text='指標2',line=5.5,cex = 0.75)

par(new=T)

plot(RMB, 指標3, axes=F, ylim=c(0,max(指標3)), xlab='', lty=3,ylab='',type='l',col='black', main='',xlim=c(7000,3400))

axis(2, ylim=c(0,max(指標2)),col='black',lwd=2,line=7)

mtext(2,text='指標3',line=9,cex = 0.75)

axis(1,pretty(range(RMB),10))

mtext('RMB',side=1,col='black',line=2,cex=0.75)

legend('topleft',cex=0.65,bty='n',legend=c('指標1','指標2','指標3'),lty=c(1,2,3))

title(main = 'base:三重坐標軸',cex=0.8,font=1)

par(op)

根據自己的需要就可以繪制一張完美的二重或三重坐標圖了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM