[2]R語言在數據處理上的稟賦之——可視化技術

R語言在可視化上可謂非常出衆,想必這也是爲什麼R語言在數據處理方面受到追捧的原因之一。

本文首發 https://program-dog.blogspot.com

上一節已經大體瞭解了R語言的基本數據類型,以及優勢所在。R的可視化技術同樣也是優勢大大滴。這也是R的數據類型爲可視化立下汗馬功勞,爲啥這樣說呢?


Java的可視化技術

我們再拿Java開刀,和做一下對比。希望Java他老爹不要見怪。大家都知道,java做圖真心說不上漂亮,爲什麼又拿java做對比呢?原因之一是我對java比較熟悉一點,之二是接下來對比的不是做圖是否美觀,而是做圖的思路。而這個做圖的思路,衆語言都是大同小異,唯獨R比較獨特。

Java中,要想做出一副圖,思路是,我想思考一下這附圖上的 點、線、面可以怎樣拆分,拆分好了我就分別畫出 點、線、面,而要把點線面組合起來,要通過所謂的控件和容器。從而完成做圖。下面舉一個例子做出餅圖:

不見圖請翻牆

代碼來自這裏,這個程序用了第三方包(否則程序更加複雜).

下面是代碼:

import javax.swing.JPanel;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.data.general.PieDataset;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;

public class PieChart_AWT extends ApplicationFrame 
{
   public PieChart_AWT( String title ) 
   {
      super( title ); 
      setContentPane(createDemoPanel( ));
   }
   private static PieDataset createDataset( ) 
   {
      DefaultPieDataset dataset = new DefaultPieDataset( );
      dataset.setValue( "IPhone 5s" , new Double( 20 ) );  
      dataset.setValue( "SamSung Grand" , new Double( 20 ) );   
      dataset.setValue( "MotoG" , new Double( 40 ) );    
      dataset.setValue( "Nokia Lumia" , new Double( 10 ) );  
      return dataset;         
   }
   private static JFreeChart createChart( PieDataset dataset )
   {
      JFreeChart chart = ChartFactory.createPieChart(      
         "Mobile Sales",  // chart title 
         dataset,        // data    
         true,           // include legend   
         true, 
         false);

      return chart;
   }
   public static JPanel createDemoPanel( )
   {
      JFreeChart chart = createChart(createDataset( ) );  
      return new ChartPanel( chart ); 
   }
   public static void main( String[ ] args )
   {
      PieChart_AWT demo = new PieChart_AWT( "Mobile Sales" );  
      demo.setSize( 560 , 367 );    
      RefineryUtilities.centerFrameOnScreen( demo );    
      demo.setVisible( true ); 
   }
}

大家可以體會一下Java做圖的複雜程度,如果你覺得Java還算簡潔,那麼且往下看。


R的可視化技術

牛刀小試

在R中做二維圖有一個基本的函數plot 。比如我們有這樣一組關於病人對不同藥量(Dosage)和不同藥物的反應的圖表:

不見圖,請翻牆

我們先創建三列數據:

dose <- c(20, 30, 40, 45, 60)
drugA <- c(16, 20, 27, 40, 60)
drugB <- c(15, 18, 25, 31, 40)

做圖:

plot(dose, drugA,type="b") 
title("Regression of MPG on Weight")

不見圖,請翻牆

這樣就做好了dose和drubA的一幅圖。這裏可以看出,dose和drubA 都被當作一個整體來對待了,又印證前面R在數據類型方面的優勢。但是現在圖表遠沒有那麼漂亮,不用着急,plot自己就可以讓圖表變得漂亮,可定製化。

plot(dose, drugA,
     type="b",              # 圖表類型,b爲折線圖
     bg="green",            # 背景顏色 綠色
     fg="blue",             # 前景顏色 藍色
     col="red",             # 折線和點的顏色 紅色
     col.axis="grey",       # 座標軸文本顏色 灰色
     col.lab="#3EB4EA",     # 座標軸標籤顏色 我也叫不上來啥顏色
     lty=3,                 # 線類型(line type) 
     lwd=3,                 # 線寬度 默認2
     pch=15,                # 點的類型 實心方塊
     cex=2,                 # 指定符號大小 2爲 200%
     col.main=rgb(1,1,1)    # 標題的顏色 
)
title("Regression of MPG on Weight(Colorful)") 

不見圖,請翻牆
幾個參數就把圖裝飾的漂漂亮亮的。那麼,R是如何做到的呢?這與R的做圖思路有相當大的關係,在R中講求的是參數配置,而非點線面本身。

二維做圖利器plot的參數配置

權限機制

R中做圖函數的參數有一些是可以共有的,比如顏色,標題,註釋座標軸等都需要顏色,還有字體等,這些就被分配到了公共參數列表之中(如par),還有參數是函數本身獨有的,比如畫圖的座標軸就只有plot函數自己有。我們應當區分對待函數共有的和獨有的參數,這樣我運用起了就自如了。

plot獨有的參數

plot的參數如下

plot(x, y = NULL, type = "p",  xlim = NULL, ylim = NULL,
     log = "", main = NULL, sub = NULL, xlab = NULL, ylab = NULL,
     ann = par("ann"), axes = TRUE, frame.plot = axes,
     panel.first = NULL, panel.last = NULL, asp = NA, ...)

看起來可能有一點暈。參數中除了最後的 (來自par) 和title有關的main,sub,xlab,ylab之外,其他都是獨有的。下面結合例子來說明常用的參數怎麼用,其他的請自行查手冊.

先列出解釋:

x, y = NULL,        x,y座標,y爲空時候自動補上y
type = "p",         圖的類型
xlim = NULL,        x座標軸的取值範圍,如c(1,10)
ylim = NULL,        y座標軸的取值範圍     
ann = par("ann"),   要不要話標籤
axes = TRUE,        要不要畫軸
x=seq(1,10,len=100)
y=x^2
plot(x,y,
    type="l",
    xlim=c(-3,13),
    ylim=c(-5,130),
    ann=FALSE,
    axes=FALSE
)
title("沒有軸,沒有標籤")

效果圖:

不見圖,請翻牆

plot的type介紹

type指的是做圖的類型,有必要介紹一下。

先列出參數:

"p" 點(points)
"l" 線(lines)
"b" 點和線(both)
"c" 線的部分(the lines part alone of "b")
"o" 線穿點 (both ‘overplotted’)
"h" 柱 (‘histogram’ like (or ‘high-density’) vertical lines)
"s" 階梯(stair steps)
"S" 階梯(other steps)
"n" 啥都不畫 (no plotting)

做圖:

opar <- par(no.readonly = TRUE)
par(mfrow=c(2,4))    #設置佈局
x=1:10
y=x
plot(x,y,type="p",main="p")
plot(x,y,type="l",main="l")
plot(x,y,type="b",main="b")
plot(x,y,type="c",main="c")
plot(x,y,type="o",main="o")
plot(x,y,type="h",main="h")
plot(x,y,type="s",main="s")
plot(x,y,type="S",main="S")
par(opar)

效果圖:

不見圖,請翻牆

說完plot獨有的參數,應該說一說其他的plot共有的或者plot也沒有的參數了。

title介紹

title 不僅僅指的主(main)題目,還包括副(sub)題目,x,y軸的標籤以及題目和圖的距離(line)和題目是否在圖內(outer).

title的參數如下:

title(main = NULL, sub = NULL, xlab = NULL, ylab = NULL,
      line = NA, outer = FALSE, ...)

前四個參數的含義如下:

main 圖像上面的主題目
sub  圖像下面的副題目
xlab x軸標籤
ylab y軸標籤

這四個參數不僅在title中可用,在其他函數裏面也可用(如plot直接可用)。

另外兩個參數含義如下:

line 題目和圖像的距離,距離太大就看不到題目了
outer 是一個布爾值,TRUE 的時候題目不會和圖像在一起,默認FALSE

這兩個參數是title獨有,不可以在plot中直接用。

其他參數,諸如 代表的是,這些參數可以從par中取。

title中的main可接受list參數。

x=seq(1,10,len=100)
y=sin(x)
plot(x,y,type="l")
title(
  main=list( # main can be a list or not ,up to you 
      "You can use main like this",
      cex=1.3,
      col="blue",
      font=3
  ),
  sub = "sub title",
  col.sub="green"  #from par
)

效果圖:

title 中的main的用法

公共參數集合——par

上面簡單介紹了plot和title函數獨有的部分,下面具體介紹一下公共參數集合par。這個函數包括了大多數plot的定製信息,簡單舉一個小例子:

par(no.readonly=TRUE)->opar #備份par

par(lty=2)                  #通過par設置參數
par(pch=17)
par(lty=2, pch=17)

dose <- c(20, 30, 40, 45, 60)
drugA <- c(16, 20, 27, 40, 60)
drugB <- c(15, 18, 25, 31, 40)
plot(dose, drugA, type="b")
title("Regression of MPG on Weight") 
par(opar)                   #還原par


用par畫出來的圖。

那麼par到底是個啥東東呢?簡而言之,par只不過儲存着plot的衆多參數而已,plot在做圖前,會去讀par裏面的變量,如果自己沒有設置,就按照par裏面的設置操作。我們把par打開看看是個什麼東西:

> summary(par())
          Length Class  Mode     
xlog      1      -none- logical  
ylog      1      -none- logical  
adj       1      -none- numeric  
ann       1      -none- logical  
ask       1      -none- logical  
bg        1      -none- character
bty       1      -none- character
cex       1      -none- numeric  
cex.axis  1      -none- numeric  
cex.lab   1      -none- numeric  
cex.main  1      -none- numeric  
cex.sub   1      -none- numeric  
cin       2      -none- numeric  
col       1      -none- character
col.axis  1      -none- character
col.lab   1      -none- character
col.main  1      -none- character
col.sub   1      -none- character
cra       2      -none- numeric  
crt       1      -none- numeric  
csi       1      -none- numeric  
cxy       2      -none- numeric  
din       2      -none- numeric  
err       1      -none- numeric  
family    1      -none- character
fg        1      -none- character
fig       4      -none- numeric  
fin       2      -none- numeric  
font      1      -none- numeric  
font.axis 1      -none- numeric  
font.lab  1      -none- numeric  
font.main 1      -none- numeric  
font.sub  1      -none- numeric  
lab       3      -none- numeric  
las       1      -none- numeric  
lend      1      -none- character
lheight   1      -none- numeric  
ljoin     1      -none- character
lmitre    1      -none- numeric  
lty       1      -none- character
lwd       1      -none- numeric  
mai       4      -none- numeric  
mar       4      -none- numeric  
mex       1      -none- numeric  
mfcol     2      -none- numeric  
mfg       4      -none- numeric  
mfrow     2      -none- numeric  
mgp       3      -none- numeric  
mkh       1      -none- numeric  
new       1      -none- logical  
oma       4      -none- numeric  
omd       4      -none- numeric  
omi       4      -none- numeric  
page      1      -none- logical  
pch       1      -none- numeric  
pin       2      -none- numeric  
plt       4      -none- numeric  
ps        1      -none- numeric  
pty       1      -none- character
smo       1      -none- numeric  
srt       1      -none- numeric  
tck       1      -none- numeric  
tcl       1      -none- numeric  
usr       4      -none- numeric  
xaxp      3      -none- numeric  
xaxs      1      -none- character
xaxt      1      -none- character
xpd       1      -none- logical  
yaxp      3      -none- numeric  
yaxs      1      -none- character
yaxt      1      -none- character
ylbias    1      -none- numeric  

我們已然發現,裏面有我們剛剛用過的比如bg,fg,col等。par 是一個函數,它的返回值是一個鏈表(List) .改變par的參數,就改變了plot的參數。

par的權限機制

par中那麼多參數,並不是每一個都可以被設定,也不是每一個都可以被任何函數所調用的。這正如一個人的家裏,不是每個人可以隨便進入或做出改變。權限機制有什麼好處呢?可以想象一下,如果沒有權限機制,那麼每一個做圖的函數都要自己定義一套參數,或者大家所有的都要用公共的參數,這帶來的不是浪費就是濫用,因此,par意識到有必要設定權限機制。

一些readonly的參數,用R.O.標識:

"cin", 
"cra",
"csi", 
"cxy", 
"din" 
"page"

僅僅可以通過par設置的參數:

"ask",
"fig", "fin",
"lheight",
"mai", "mar", "mex", "mfcol", "mfrow", "mfg",
"new",
"oma", "omd", "omi",
"pin", "plt", "ps", "pty",
"usr",
"xlog", "ylog",
"ylbias"

可以被其他函數調用的參數:剩餘其他。

總結

鑑於篇幅長度,par的使用下一節再介紹。

R語言天生就有可視化的優越條件,簡單而且可配置性強。讓人專注於數據處理而非代碼本身,這又是R語言在數據處理上的稟賦。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章