1. 程式人生 > >R語言繪製雙座標圖

R語言繪製雙座標圖

之前公眾號推送了一系列關於使用ggplot2包繪製統計圖形的文章,有網友詢問是否可以繪製雙軸的統計圖形。很抱歉,Hradly在設計ggplot2包時就沒有將雙軸圖形功能考慮進來。難道R語言就無法繪製雙軸圖形了嗎?非也,R不僅是統計學家的標準工具,也是一款繪製圖形的理想工具。下面就跟大家介紹plotrix包中的twoord.plot()函式和twoord.stackplot()函式,它們可以實現雙座標軸圖形的繪製。

twoord.plot()函式語法及引數含義:

  1. twoord.plot(lx,ly,rx,ry,data=NULL,main="",
  2. xlim=NULL,lylim
    =NULL,rylim=NULL,
  3. mar=c(5,4,4,4),lcol=1,rcol=2,
  4. xlab="",lytickpos=NA,ylab="",
  5. ylab.at=NA,rytickpos=NA,rylab="",
  6. rylab.at=NA,lpch=1,rpch=2,
  7. type="b",xtickpos=NULL,
  8. xticklab=NULL,halfwidth=0.4,
  9. axislab.cex=1,do.first=NULL,...)

lx,ly,rx,ry:分別指定左座標軸和右座標軸的值,必須是連續的值

data:需要繪製雙軸圖形的資料框

main:為圖形指定標題

xlim:限制橫座標值的範圍

lylim,rylim:限制左右縱座標值的範圍

mar:設定圖形邊界距,預設值為(5,4,4,4)

lcol,rcol:設定左右座標軸的顏色,這樣可以起到圖例的作用

xlab:設定橫座標軸標籤

lytickpos:設定左座標軸刻度標籤的位置

ylab:設定左座標軸標籤

ylab.at:設定左座標軸標籤位置

rytickpos:設定右座標軸刻度標籤的位置

rylab:設定又座標軸標籤

rylab.at:設定右座標軸標籤位置

lpch,rpch:設定左右座標軸圖形的外觀

type

:指定圖形型別

xtickpos:設定橫座標軸刻度標籤位置

xticklab:設定橫座標軸刻度標籤

halfwidth:設定使用者給定條形圖寬度的一半

axislab.cex:設定座標軸標籤和刻度標籤的大小

do.first:通過該引數可以往圖形中新增背景色或網格線

下面通過案例來說明twoord.plot()函式的應用:

library(plotrix)

繪製雙軸的兩個線圖

Date <- seq(from = as.Date(‘2015-01-01’), to = as.Date(‘2015-12-01’),
by = ‘month’)

Consumers <- c(100,80,120,153,200,188,220,322,300,321,282,304)

Amount <- c(1000,840,1458,1844,2045,2000,2548,5081,5000,5200,4800,4971)

df1 <- data.frame(Date = Date, Consumers=Consumers, Amount = Amount)

twoord.plot(lx = df1$Date, ly = df1$Consumers, rx = df1$Date, ry = df1$Amount,
main = ‘雙軸的兩條線圖’, xlab = ‘月份’, ylab = ‘會員人數’, rylab = ‘總消費額’, type = c(‘line’,’line’))

雖然雙座標軸圖形已經繪製好,但圖中有幾個不滿意的地方

1)橫座標軸的刻度標籤不是正確的日期格式

2)右座標軸刻度標籤很擠

3)圖形不炫酷,想新增背景色或網格線

好,這些不滿意的地方都不是問題,twoord.plot()函式可以輕鬆搞定:

1)通過xticklab引數重新設定橫座標軸的刻度標籤

2)通過rytickpos引數重新設定刻度標籤

3)通過do.first引數給圖形新增背景色和網格線

twoord.plot(lx = df1$Date, ly = df1$Consumers, rx = df1$Date, ry = df1$Amount,
main = ‘雙軸的兩條線圖’, xlab = ‘月份’, ylab = ‘會員人數’, rylab = ‘總消費額’, type = c(‘line’,’line’),
xtickpos=as.numeric(df1$Date), xticklab = as.character(df1$Date), rytickpos
= seq(500,5000,by = 1500), do.first = ‘plot_bg(col = \’gray\’); grid(col
= \’white\’, lty = 2)’)

這樣的圖形結果要比上面的圖看起來舒服多了。如果想把左座標軸的會員人數用條形圖表示,右座標軸的總消費額用線條表示,該如何操作呢?很簡單,只需將type引數設定為(‘bar’,’line’)就可以了:

twoord.plot(lx = df1$Date, ly = df1$Consumers, rx = df1$Date, ry = df1$Amount,
lcol = ‘steelblue’, main = ‘雙軸的兩條線圖’, xlab = ‘月份’, ylab = ‘會員人數’, rylab
= ‘總消費額’, type = c(‘bar’,’line’), xtickpos=as.numeric(df1$Date), xticklab
= as.character(df1$Date), rytickpos = seq(500,5000,by = 1500), do.first
= ‘plot_bg(col = \’gray\’); grid(col = \’white\’, lty = 2)’)

哎?又有問題了,這個條形圖怎麼這麼細窄?超級難看。不要著急,只要稍稍調整halfwidth引數的大小即可,這裡設定為8:

twoord.plot(lx = df1$Date, ly = df1$Consumers, rx = df1$Date, ry = df1$Amount,
lcol = ‘steelblue’, main = ‘雙軸的兩條線圖’, xlab = ‘月份’, ylab = ‘會員人數’, rylab
= ‘總消費額’, type = c(‘bar’,’line’), xtickpos=as.numeric(df1$Date), xticklab
= as.character(df1$Date), rytickpos = seq(500,5000,by = 1500), halfwidth
= 8, do.first = ‘plot_bg(col = \’gray\’); grid(col = \’white\’, lty = 2)’)

這會兒圖形正常了。還記得直方圖是如何繪製的嗎?hist()函式,直方圖+核密度圖是如何繪製的?hist()函式+lines()函式:

set.seed(1000)

x = rnorm(1000,10,3)

h <- hist(x, breaks = 50)

繪製直方圖和核密度圖

hist(x, breaks = 50, col = ‘steelblue’)

lines(density(x), col = ‘red’)

哎?核密度線怎麼成了一條直線了?原來是因為直方圖高度對於的頻次與核密度值不是一個量綱,即頻次在0~60之間,而核密度值在0~1之間。如果要使核密度曲線體現出來,必須將hist()函式中freq引數設定為FALSE:

繪製直方圖和核密度圖

hist(x, breaks = 50, col = ‘steelblue’, freq = FALSE)

lines(density(x), col = ‘red’, lwd=2)

如果我既想看到不同組的頻次,又想看到對應的密度值該怎麼辦呢?這個時候就需要繪製雙軸圖了:

x1 <- h$mids

y1 <- h$counts

x2 <- seq(min(x), max(x), by = 0.01)

y2 <- dnorm(seq(min(x), max(x), by = 0.01),10,3)

twoord.plot(lx = x1, ly = y1, rx = x2, ry = y2, type=c(‘bar’,’l’), lcol
= ‘steelblue’, rcol = ‘red’, ylab = ‘Counts’, rylab = ‘Density’, main =
‘Histogram and density curve’, halfwidth=0.2, lylim = c(0,max(y1)+1), rylim
= c(0,0.2),lwd=2)

關於twoord.plot()函式,最後再介紹一種圖,帕累託圖形。即圖形中包一個縱座標軸表示絕對數量,另一個縱座標軸表示累計百分比。實現該圖指令碼如下:

type <- 1:7

absolute <- c(12,15,20,28,11,5,7)

cum_per <- cumsum(absolute)/sum(absolute)

twoord.plot(lx = type, ly = absolute, rx = type, ry = cum_per, type=c(‘bar’,’l’),
lcol = ‘steelblue’, rcol = ‘red’, ylab = ‘總數’, rylab = ‘累計百分比%’, main =
‘帕累託圖’, xtickpos=type, xticklab = c(‘A’,’B’,’C’,’D’,’E’,’F’,’G’))

下面再看一下twoord.stackplot()函式,該函式與twoord.plot()的不同之處在於,其可以繪製堆疊圖,函式具體語法和引數含義如下:

twoord.stackplot(lx, rx, ldata, rdata,

  1. lcol, rcol, ltype, rtype,
  2. border, rylab, lylab,

xlab,

  1. ..., incrylim=NULL,halfwidth=0.4,
  2. leftfront=FALSE,
  3. mar = c(5,4,4,4))

lx,rx:指定左右橫座標軸的值

ldata,rdata:指定左右縱座標軸的值

lcol, rcol:指定左右座標軸的顏色

ltype, rtype:指定左右座標軸線的型別

border:指定條形圖邊框顏色

rylab,lylab:指定左右縱座標軸標籤

xlab:指定橫座標軸標籤

incrylim:增加座標軸值的範圍

halfwidth:設定使用者給定條形圖寬度的一半

leftfront:如果leftfront設定為TRUE的話,則左座標軸將置於頂層

mar:設定圖形邊界距,預設值為(5,4,4,4)

現在有一個場景是這樣的,需要繪製某APP在2015年各月中新老會員人數及新會員所佔比重

set.seed(1111)

Date <- 1:12

Old <- round(runif(12, 100,300))

New <- round(runif(12, 50,120))

Ratio <- New/(New+Old)

twoord.stackplot(lx=Date, rx=Date, ldata=cbind(Old, New), rdata=Ratio,
lcol=c(‘steelblue’,’orange’), rcol=’red’, ltype=”bar”,
rtype=’l’, border=”grey80”, lylab = ‘人數’, rylab = ‘新客比例’, xlab=’月份’,
main=’新老客佔比’, incrylim=0.1)

上圖能夠很高的看出新老客之間的數量對比,同時也能看出新客的趨勢線,唯一不足的是,沒有圖例,下面就以圖層的概念,在該圖的基礎上新增一下圖例:

擴充套件繪圖區域並新增圖層

par(xpd=TRUE)

par(new=TRUE)

在原來圖形的基礎上繪製一張空圖

plot(0:1, 0:1, type=”n”, xlab=””,ylab=””,
axes=FALSE)

新增左座標軸軸圖例

legend(0, 1.5, leg=c(‘老客’, ‘新客’), fill=c(‘steelblue’,’orange’), bty =
‘n’)

新增右座標軸軸圖例

legend(-0.03, 1.25, leg=’新客比例’, col=’red’, lty = 1, bty = ‘n’)

par(xpd=FALSE, new=FALSE)

非常完美,根據以上的場景要求,就繪製完一幅圖形了,而且也能迅速的瞭解到圖所表達的內容。

劉順祥,資料分析師,熱愛資料分析與挖掘工作,擅長使用R語言,目前自學Python語言。