《R語言實戰》第3章 圖形初階&第4章 基本數據管理 學習筆記

第3章 圖形初階

圖形是數據分析師觀察和展示數據的重要工具。

3.1 使用圖形

構建散點圖並保存pdf

> pdf("mygraph.pdf") # 保存pdf> attach(mtcars) # 載入mtcars數據表> plot(wt, mpg) # 繪製散點圖> abline(lm(mpg~wt)) # 最優擬合曲線> title("Regression of MPG on Weight") # 表標題> detach(mtcars) # 釋放mtcars> dev.off() # 輸出圖形

還可以使用jpeg(),bmp()等第一章提到過的語句保存為不同形式的圖形。

繪製多個圖形,後面的圖形會覆蓋掉先前的圖形,如何才能創建多個圖形並隨時查看每一個,這裡有三個方法:

  1. 方法一:通過dev.new()創建新的窗口,繪製圖形,然後再次創建
  2. 方法二:勾選「歷史」History -> 「記錄」Recording 通過 「上一個」Previous和「下一個」Next查看已經繪製的圖形。
  3. 方法三:可以使用dev.new(),dev.next(),dev.prev(),dev.set()和dev.off()同時打開多個圖形窗口,細節參考help(dev.cur)

拓展:plot()的類型選擇與dev類函數

1. plot()的類型選擇

plot()函數,屬於graphics包中,plot(a,b,type="value")

type:以什麼樣的形式來表現a,b之間的關係:

  • "p":點,point
  • "l":線,lines
  • "b":斷點為點,線連接,點線不相交,both
  • "c":僅線,不連續
  • "o":點、線且相交,overplot
  • "n":空圖,no plotting

2. dev類函數

  1. 函數功能:多個圖形設備之間提供控制功能。
  2. 使用方式:
  • 所有關於圖形的操作都在一個設備中進行,即僅有一個設備是「活躍設備」;
  • 「空設備」null device 總是打開並佔位;
  • 任何使用空設備的操作,會導致另外一個設備被打開,一旦有其他設備被打開,則空設備不再活躍;
  • 設備有格子的名字,同時有編號(1到63);
  • 空設備的編號始終為1;
  1. dev.list() 返回打開的設備的名單列表,但不包括空設備;
  2. dev.off() 關閉指定設備(預設狀態下為當前活躍設備);
    • 關閉後,其他打開設備變為活躍;
    • 關閉後,返回新打開的活躍設備的名字和編號;
    • 設備1不能被關閉,即對設備1的關閉操作是錯誤的;
  3. graphics.off() 關閉所有打開的設備;
  4. dev.set() 指定一個特定的設備為活躍;
    • 若無指定,相當於dev.next();
    • 若指定為1,打開新的設備並設為活躍,返回新設備的名字和編號;
  5. dev.new() 打開一個新的設備。R經常根據需要自動打開新的設備,但使用命令可以跨平台打開更多設備;返回新設備名字和編號;
  6. dev.cur() 查看當前的活躍設備,返回當前活躍設備的名字和編號的向量,返回1即空設備;
  7. dev.next() 查看緊隨當前活躍進程的下一個進程,返回其名字和編號;
  8. dev.prev() 查看當前活躍進程的前一個進程,返回其名字和編號;

plot()和dev類函數測試

> dev.list()NULL> x <- c(1,2,3,4)> y <- c(2,4,6,8)> pdf("C:/Users/Administrator/Desktop/newgraph.pdf")> plot(x,y,type="o") # 設備2> png("C:/Users/Administrator/Desktop/newgraph.png")> plot(x,y,type="p") # 設備3> jpeg("C:/Users/Administrator/Desktop/newgraph.jpeg")> plot(x,y,type="b") # 設備4> bmp("C:/Users/Administrator/Desktop/newgraph.bmp")> plot(x,y,type="l") # 設備5> dev.new() NULL> dev.cur()RStudioGD 6> dev.new(8)NULL> dev.cur()windows 8 > dev.cur() ### 手動關閉窗口後,活動設備變為設備2pdf 2> dev.list() pdf png jpeg bmp RStudioGD png 2 3 4 5 6 7 windows 8> dev.off() # 關閉活動設備後,活動設備變為設備3png 3 > dev.set(4) # 設置活動設備為4jpeg 4 > dev.next() # 活動設備後一個bmp 5 > dev.prev() # 活動設備前一個png 3 > graphics.off() # 關閉所有

3.2 一個簡單的例子

一個假想的數據集:

劑 量對藥物 A 的響應對藥物 B 的響應201615302018402725454031606040

> 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")

3.3 圖形參數

通過函數par()可以指定一幅圖形的多個特徵(字體、顏色、坐標軸、標籤),這種方式的參數值除非再次被修改,否則將在會話結束前一直有效。 其 調 用 格 式 為 par(optionname=value, optionname=name,...)。

  • par() (不加參數地執行)將生成一個含有當前圖形參數設置的列表。
  • par(no.readonly=TRUE)可以生成一個可以修改的當前圖形參數列表。

> opar <- par(no.readonly=TRUE) # 將原參數列表保存> par(lty=2, pch=17) # 設置新參數虛線(lty=2)實心三角(pch=17)> plot(dose, drugA, type="b") # 重繪圖型> par(opar) # 恢復原始配置

> par(lty=2)> par(pch=17)# par也可以分開寫,似乎需要寫在創建設備之後才能生效> plot(dose, drugA, type="b", lty=2, pch=17)

也可以通過上述代碼指定僅對本圖有效(提供optionname=value的鍵值對)生成同樣的圖形。

具體可使用的參數,參考每個特定繪製函數的幫助:「?plot」,「?hist」或「?boxplot」。

3.3.1 符號和線條

符號和線條類型的參數

參數描述pch指定繪製點時使用的符號cex指定符號的大小。 cex 是一個數值,表示繪圖符號相對於默認大小的縮放倍數。默認大小為 1, 1.5 表示放大為默認值的 1.5 倍, 0.5 表示縮小為默認值的 50%,等等lty指定線條類型lwd指定線條寬度。 lwd 是以默認值的相對大小來表示的(默認值為 1) 。例如, lwd=2 將生成一條兩倍於默認寬度的線條

參數pch可指定的繪圖符號

參數lty可指定的線條類型

3.3.2 顏色

參 數描 述col默認的繪圖顏色。某些函數(如 lines 和 pie)可以接受一個含有顏色值的向量並自動循環使用。col.axis坐標軸刻度文字的顏色col.lab坐標軸標籤(名稱)的顏色col.main標題顏色col.sub副標題顏色fg圖形的前景色bg圖形的背景色

col參數:例如,如果設定 col=c("red", "blue")並需要繪製三條線,則第一條線將為紅色,第二條線為藍色,第三條線又將為紅色

例如,表示白色的等價方式:

  • 通過下標 col=1
  • 顏色名稱 col="white"
  • 十六進位的顏色值 col="#FFFFFF"
  • RGB值 col=rgb(1,1,1)
  • HSV值 col=hsv(0,0,1)

函數colors()可以返回所有可用顏色的名稱。 參照Earl F.Glynn為R中的在線圖表

一些創建連續型顏色向量的函數:包括rainbow()、 heat.colors()、 terrain.colors()、 topo.colors()以及cm.colors()。比如rainbow(10)可以生成10種連續的「彩虹型」顏色。

特別的,可以使用RColorBrewer擴展包來創建顏色值向量。(install.packages("RColorBrewer")需提前安裝)

RColorBrewer顏色代碼

> library(RColorBrewer)> n <- 7> mycolors <- brewer.pal(n, "Set1")> barplot(rep(1,n), col=mycolors)

> n <- 10> mycolors <- rainbow(n)> pie(rep(1, n), labels=mycolors, col=mycolors)> mygrays <- gray(0:n/n)> pie(rep(1, n), labels=mygrays, col=mygrays)

3.3.3 文本屬性

用於指定文本大小的參數

參 數描 述cex表示相對於默認大小縮放倍數的數值。默認大小為 1, 1.5 表示放大為默認值的 1.5 倍, 0.5 表示縮小為默認值的 50%,等等cex.axis坐標軸刻度文字的縮放倍數。類似於 cexcex.lab坐標軸標籤(名稱)的縮放倍數。類似於 cexcex.main標題的縮放倍數。類似於 cexcex.sub副標題的縮放倍數。類似於 cexfont整數。用於指定繪圖使用的字體樣式。 1=常規, 2=粗體, 3=斜體, 4=粗斜體, 5=符號字體(以 Adobe符號編碼表示)font.axis坐標軸刻度文字的字體樣式font.lab坐標軸標籤(名稱)的字體樣式font.main標題的字體樣式font.sub副標題的字體樣式ps字體磅值(1 磅約為 1/72 英寸)。文本的最終大小為 ps*cexfamily繪製文本時使用的字體族。標準的取值為 serif(襯線) 、 sans(無襯線)和 mono(等寬)

> par(font.lab=3, cex.lab=1.5, font.main=4, cex.main=2)

之後創建的圖形將擁有:斜體;1.5倍的坐標軸標籤名稱;標題粗斜體;標題的縮放倍數2倍文本;

創建字體映射(Window):

如果對family="serif"設置的結果不滿意,可以使用函數windowsFont()來創建這類映射。

> windowsFonts(+ A=windowsFont("Arial Black"),+ B=windowsFont("Bookman Old Style"),+ C=windowsFont("Comic Sans MS")+ )> par(family="A")

使用對應映射,即可設置繪圖字體為:Arial Black

在Mac上,請改用quartzFonts()。

對於PDF格式,可以 使 用 names(pdfFonts()) 找 出 你 的 系 統 中 有 哪 些 字 體 是 可 用 的 , 然 後 使 用 pdf(file="myplot.pdf", family="fontname")來生成圖形。

對於以PostScript格式輸出的圖形,則可以對應地使用names(postscriptFonts())和postscript(file="myplot.ps", family="fontname")。

3.3.4 圖形尺寸與邊界尺寸

控制圖形尺寸和邊界大小的參數

參 數描 述pin以英寸表示的圖形尺寸(寬和高)mai以數值向量表示的邊界大小,順序為「下、左、上、右」,單位為英寸mar以數值向量表示的邊界大小,順序為「下、左、上、右」,單位為英分。默認值為 c(5, 4, 4, 2) + 0.1

> par(pin=c(4,3), mai=c(1,.5, 1, .2))

生成一幅4X3英寸大小,上下邊界為1,左邊界為0.5,右邊界為0.2英寸的圖形。

圖形外觀測試輸出

> dose <- c(20,30,40,45,60)> drugA <- c(16,20,27,40,60)> drugB <- c(15,18,25,31,40)> > opar <- par(no.readonly = TRUE) # 保存原始配置> par(pin=c(2,3)) # 圖片尺寸2 X 3> par(lwd=2,cex=1.5) # 線條寬度2倍,字體大小1.5倍> par(cex.axis=.75,font.axis=3) # 軸倍數0.75,軸形式,斜體> plot(dose,drugA,type="b",pch=19,lty=2,col="red")> plot(dose,drugB,type="b",pch=23,lty=6,col="blue",bg="green")> # 設置了圖形樣式、線性、顏色和背景色(drugB)> par(opar) # 還原

了解具體的圖形參數信息可以查閱help(par)。

3.4 添加文本、自定義坐標軸和圖例

> plot(dose, drugA, type="b",+ col="red", lty=2, pch=2, lwd=2,+ main="Clinical Trials for Drug A",+ sub="This is hypothetical data",+ xlab="Dosage", ylab="Drug Response",+ xlim=c(0, 60), ylim=c(0, 70))

除了設置形式為b、圖形顏色為紅色、圖形為2型、線性寬度2倍外,添加了標題(main),副標題(sub),坐標軸標籤(xlab,ylab)和坐標軸範圍(xlim,ylim)。

並非所有的函數都支持這些選項,同時針對高級繪圖函數已經包含的默認標題和標籤可以通過「ann=FALSE」進行移除。

3.4.1 標題

使用title()函數可以針對圖形添加標題和坐標軸標籤,例如:

> title(main="My Title", col.main="red",+ sub="My Subtitle", col.sub="blue",+ xlab="My X label", ylab="My Y label",+ col.lab="green", cex.lab=0.75)

從上例可以看出,title除了能設置main,sub,xlab,ylab這種常規的標題屬性,也可以添加針對標題的顏色、比例等信息。

函數title()一般來說被用於添加信息到一個默認標題和坐標軸標籤被ann=FALSE選項移除的圖形中。

3.4.2 坐標軸

通過axis()函數來創建坐標軸,而非R的默認坐標軸:

axis(side, at=, labels=, pos=, lty=, col=, las=, tck=, ...)

坐標軸相關的選項

選 項描 述side一個整數,表示在圖形的哪邊繪製坐標軸(1=下, 2=左, 3=上, 4=右)at一個數值型向量,表示需要繪製刻度線的位置labels一個字元型向量,表示置於刻度線旁邊的文字標籤(如果為NULL,則將直接使用 at 中的值)pos坐標軸線繪製位置的坐標(即與另一條坐標軸相交位置的值)lty線條類型col線條和刻度線顏色las標籤是否平行於(=0)或垂直於(=2)坐標軸tck刻度線的長度,以相對於繪圖區域大小的分數表示(負值表示在圖形外側,正值表示在圖形內側, 0表示禁用刻度, 1表示繪製網格線);默認值為–0.01(…)其他圖形參數

參數axes=FALSE 將禁用全部坐標軸(包括框線,除非添加了frame.plot=TRUE)。

參數xaxt="n"和yaxt="n"將分別禁用x軸和y軸(留框線,去刻度)

綜合代碼示例

> 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) # b型,21符,紅色,線型3,禁用刻度,清除默認參數> lines(x, z, type="b", pch=22, col="blue", lty=2)# 添加一條x對10/x的直線,22符號,顏色藍,線型2> axis(2, at=x, labels=x, col.axis="red", las=2)# 繪製坐標軸:左邊,文字標籤x,內容x,軸顏色為紅,標籤垂直於坐標軸> axis(4, at=z, labels=round(z, digits=2),+ col.axis="blue", las=2, cex.axis=0.7, tck=-.01)# 繪製坐標軸:右邊,文字標籤z,內容1/y,軸為藍色,垂直於坐標軸,軸字體倍數0.7,刻度線長度在圖形外側0.01長度> mtext("y=1/x", side=4, line=3, cex.lab=1, las=2, col="blue")# 文字標籤:"y=1/x" 在右側輸出,標籤顯示在離坐標軸3的位置,坐標軸正常縮放,垂直,顏色為藍色> title("An Example of Creative Axes",+ xlab="X values",+ ylab="Y=X")# 主標題,x,y軸標題> par(opar)

通過lines()語句,你可以為一幅現有圖形添加新的圖形元素。

函數mtext()用於在圖形的邊界添加文本。

如果需要創建次刻度線,需要安裝Hmisc包,並使用minor.tick()函數。詳情略。

3.4.3 參考線

函數abline()可以用來為圖形添加參考線。其使用格式為:

abline(h=yvalues, v=xvalues)

> abline(h=yvalues, v=xvalues)> abline(h=c(1,5,7))# 在y為1,5,7的位置添加了水平實線> abline(v=seq(1, 10, 2), lty=2, col="blue")# 在x為1,3,5,7,9的位置添加了垂直的藍色虛線

相應的,參考線

3.4.4 圖例

可以使用函數legend()來添加圖例

legend(location, title, legend, ...)

圖例選項

  • location:圖例的位置:(x,y坐標;傳參1滑鼠點擊;使用關鍵字 bottom、 bottomleft、 left、 topleft、 top、topright、 right、 bottomright 或 center 放置圖例(inset=指定圖例向圖形內側移動的大小,用分數表示);)
  • title: 圖例標題的字元串(可選)
  • legend:圖例標籤組成的字元型向量
  • ...:其他選項:col=,pch=,lwd=或lty=加上寬度值或類型值組成的向量。(fill=顏色可以創建顏色填充)

其他的比如指定盒子樣式的bty、指定背景色的bg、指定大小的cex,以 及指定文本顏色的text.col。指定horiz=TRUE將會水平放置圖例,而不是垂直放置,更多細節參考:help(legend)。

依劑量對比藥物A和藥物B的相應情況

> dose <- c(20, 30, 40, 45, 60)> drugA <- c(16, 20, 27, 40, 60)> drugB <- c(15, 18, 25, 31, 40)# 數據集> opar <- par(no.readonly=TRUE)# 備份> par(lwd=2,cex=1.5,font.lab=2)# 通用參數> plot(dose,drugA,type="b",pch=15,lty=1,col="red",+ ylim=c(0,60),main="Drug A vs. Drug B",sub="A&B",+ xlab="Drug Dosage",ylab="Drug Response")# 繪製dose,drugA圖形> lines(dose, drugB, type="b",+ pch=17, lty=2, col="blue")# 追加dose,drugB圖形> abline(h=c(30),lwd=1.5,lty=2,col="gray")# 參考線> library(Hmisc)# 添加次要刻度線> minor.tick(nx=3, ny=3, tick.ratio=0.5)> legend("topleft", inset=.05, title="Drug Type", c("A","B"),+ lty=c(1, 2), pch=c(15, 17), col=c("red", "blue"))# 添加圖例 其中inset=.05為相對位置,其他參數與線性對應> par(opar)

3.4.5 文本標註

可以通過text()和mtext()將文本添加到圖形上。不同的是text()是向繪圖區域內部添加文本,而mtext()則向圖形的四個邊界之一添加文本。

text(location,"text to place",ps,...)mtext("text to place",aside,line=n,...)

  • location 文本的位置參考。可以是x,y坐標,也可以用(1)精準的用滑鼠確認位置;
  • pos 文本相對位置,1下2左3上4右,可以用offset=設置偏移量(單字元寬度比例);
  • aside 文本的邊。1下2左3上4右,可以指定line=來內移或外移文本。adj=0與左下對齊adj=1右上對齊;
  • 字體調整 cex,col,font 字型大小、顏色和字體樣式

文本標註實例

> plot(wt, mpg,+ main="Mileage vs. Car Weight",+ xlab="Weight", ylab="Mileage",+ pch=18, col="blue")> text(wt, mpg,+ row.names(mtcars),+ cex=0.6, pos=4, col="red")> detach(mtcars)

不同字體族的代碼

> opar <- par(no.readonly=TRUE)> par(cex=1.5)> plot(1:7,1:7,type="n")> text(3,3,"Example of default text")> text(4,4,family="mono","Example of mono-spaced text")> text(5,5,family="serif","Example of serif text")> par(opar)

3.4.6 數學標註

這裡類似於TeX中的寫法為圖形添加數學符號和公式。可以參閱help(plotmath)參與更多細節和示例。

可以嘗試執行demo(plotmath)查看即時效果。

函數plotmath()可以為圖形主體或邊界上的標題、坐標軸名稱或文本標註添加數學符號。

3.5 圖形的組合

在R中使用函數par()或layout()可以組合多張圖為一幅總括圖形。

你可以在par()函數中使用圖形參數mfrow=c(nrows, ncols)來創建按行填充的、行數為nrows、列數為ncols的圖形矩陣。

另外,可以使用mfcol=c(nrows, ncols)按列填充矩陣。

四幅圖形並將其排布在兩行兩列中:

> opar <- par(no.readonly=TRUE)> par(mfrow=c(2,2))> plot(wt,mpg, main="Scatterplot of wt vs. mpg")> plot(wt,disp, main="Scatterplot of wt vs. disp")> hist(wt, main="Histogram of wt")> boxplot(wt, main="Boxplot of wt")> par(opar)> detach(mtcars)

三行一列排布三幅圖形

> opar <- par(no.readonly=TRUE)> par(mfrow=c(3,1))> hist(wt)> hist(mpg)> hist(disp)> par(opar)> detach(mtcars)

注意,高級繪圖函數hist()包含了一個默認的標題(使用main=""可以禁用它,抑或使用ann=FALSE來禁用所有標題和標籤)。

有選擇地在layout()函數中使用widths=和heights=兩個參數可以更精確的空值每幅圖形的大小。(具體可以通過數值指定比例,或通過lcm()來指定絕對長度(厘米))

1圖高度是2圖的1/2,右下圖形的寬度是左下圖形寬度的1/3

> layout(matrix(c(1, 1, 2, 3), 2, 2, byrow = TRUE),+ widths=c(3, 1), heights=c(1, 2))# 將c(1,1,2,3)輸入一個2x2的矩陣中,widths/heights 按比例組成向量> hist(wt)> hist(mpg)> hist(disp)> detach(mtcars)

layout()函數能夠讓我們輕鬆地控制最終圖形中的子圖數量和擺放方式,help(layout)查看更多細節。

同時可以通過fig=完成對圖形布局的精細控制能力:

代碼清單

> opar <- par(no.readonly=TRUE)> par(fig=c(0, 0.8, 0, 0.8))> plot(mtcars$wt, mtcars$mpg,+ xlab="Miles Per Gallon",+ ylab="Car Weight")> par(fig=c(0, 0.8, 0.55, 1), new=TRUE)> boxplot(mtcars$wt, horizontal=TRUE, axes=FALSE)> par(fig=c(0.65, 1, 0, 0.8), new=TRUE)> boxplot(mtcars$mpg, axes=FALSE)> mtext("Enhanced Scatterplot", side=3, outer=TRUE, line=-3)> par(opar)

請試想完整的繪圖區域:左下角坐標為(0, 0),而右上角坐標為(1, 1)。參數fig=的取值是一個形如c(x1, x2, y1, y2)的數值向量。注意設定參數new=TRUE,否則fig默認繪製一幅新圖。

總結筆記

本章學習了R做圖的基本方法,R的做圖功能十分強大,而其思想也與matplotlib相似,鑒於函數參數較多,下面進行簡單的總結:

plot中:

  • pch 設定符號類型
  • cex 設定符號大小
  • lty 設置連線類型
  • lwd 設置線寬

特定值設定:

  • col 顏色(col=1、 col="white"、 col="#FFFFFF"、col=rgb(1,1,1)和col=hsv(0,0,1))
    • fg 前景色
    • bg 背景色
  • cex 大小倍數
  • font 字體(1=常規, 2=粗體, 3=斜體, 4=粗斜體, 5=符號字體)

對應的:.axis 坐標軸;.lab 坐標軸標籤(名稱);.main/.sub 主/副標題

常用的圖形尺寸和邊界尺寸:

  • pin 英寸
  • mai 數值向量的邊界大小,英寸。
  • mar 數值向量的邊界大小,英分。默認值c(5,4,4,2)+0.1

文本標註:

  • xlab/ylab 坐標軸標籤
  • xlim/ylim 坐標軸範圍
  • title() 標題(一般添加在用ann=FALSE移除的圖形中)
  • axis() 坐標軸
    • side 哪邊? 1下2左3上4右
    • at 一個數值型向量,表示需要繪製刻度線的位置
    • labels 刻度線旁的文字標籤
    • pos 坐標軸相交值
    • lty 線類型
    • col 線顏色
    • las 水平0垂直2
    • tck 刻度線長度,負值在外側,正值在內側
  • abline() 參考線
  • legend() 圖例
    • location 位置(bottom、 bottomleft、 left、 topleft、 top、topright、 right、 bottomright 或 center 放置圖例。)
    • title 圖例字元串
    • legend 標籤組成的字元型向量
  • text() 向繪圖區域內部添加文本
  • mtext() 向圖形的四個邊界之一添加文本
    • location 位置
    • pos 文本相對於位置參數的方位。1下2左3上4右,offset= 作為偏移量
    • side 文本的邊 line= 移動文本 adj=0向左下對齊 adj=1右上對齊

圖形的組合:

  • par(mfrow=c(nrows, ncols))/par(mfcol=c(nrows, ncols))按行/列填充矩陣
  • layout() 可以用穿件矩陣的方式:matrix(c(1, 1, 2, 3), 2, 2, byrow = TRUE), widths=c(3, 1), heights=c(1, 2)進行排布,寬度比/高度比
  • 使用圖形參數fig=c(x,y,X,Y),進行精細化的圖形布局(左下角為0,0/右上角為1,1,進行繪製)。

第4章 基本數據管理

數據的前期準備通常會花費一半以上的時間。

4.1 示例

以下示例是研究男性和女性在領導各自企業方式上的不同。

  • 處於管理崗位的男性和女性在聽從上級的程度上是否有所不同?
  • 這種情況是否依國家的不同而有所不同,或者說這些由性別導致的不同是否普遍存在?

現在擁有讓多個國家的經理人的上司對其服從程度打分,類似於:

12345非常不同意不同意既不同意也不反對同意非常同意

得到的表格為:

領導行為的性別差異

經理人日期國籍性別年齡Q1Q2Q3Q4Q5110/24/14USM3254555210/28/14USF4535255310/01/14UKF2535552410/12/14UKM39334505/01/14UKF9922121

數據集代碼

> manager <- c(1, 2, 3, 4, 5)> date <- c("10/24/08", "10/28/08", "10/1/08", "10/12/08", "5/1/09")> country <- c("US", "US", "UK", "UK", "UK")> gender <- c("M", "F", "F", "M", "F")> age <- c(32, 45, 25, 39, 99)> q1 <- c(5, 3, 3, 3, 2)> q2 <- c(4, 5, 5, 3, 2)> q3 <- c(5, 2, 5, 4, 1)> q4 <- c(5, 5, 5, NA, 2)> q5 <- c(5, 5, 2, NA, 1)> leadership <- data.frame(manager, date, country, gender, age,+ q1, q2, q3, q4, q5, stringsAsFactors=FALSE)

4.2 創建新變數

特別注意:

  • ^或** 求冪
  • x%%y 求餘數除法
  • x%/%y 整數除法(地板除)

在數據框mydata計算和和平均數的示例

> mydata<-data.frame(x1 = c(2, 2, 6, 4),+ x2 = c(3, 4, 2, 8))# 第一種方式:> mydata$sumx <- mydata$x1 + mydata$x2> mydata$meanx <- (mydata$x1 + mydata$x2)/2# 第二種方式:> attach(mydata)> mydata$sumx <- x1 + x2> mydata$meanx <- (x1 + x2)/2> detach(mydata)# 第三種方式:(推薦)> mydata <- transform(mydata,+ sumx = x1 + x2,+ meanx = (x1 + x2)/2)

推薦使用transform()函數進行數據框內的創建新變數運算。

4.3 變數的重編碼

  • 將連續變數修改為一組類別值;
  • 將誤編碼替換為正確值;
  • 基於一組條件進行邏輯判斷變數;

特別注意(邏輯運算):

  • != 不等於
  • == 嚴格等於(慎用)
  • ! 非
  • | 或
  • & 和
  • isTRUE(x) 判斷x是否為TRUE

下面進行如下操作:標記 leadership$age == 99 為缺失值,大於75歲為Elder,小於55歲為Young,中間為Middle Aged。

> leadership$age[leadership$age == 99] <- NA> leadership$agecat[leadership$age > 75] <- "Elder"> leadership$agecat[leadership$age >= 55 &+ leadership$age <= 75] <- "Middle Aged"> leadership$agecat[leadership$age < 55] <- "Young"

> leadership$age[leadership$age == 99] <- NA> leadership <- within(leadership,{+ agecat <- NA+ agecat[age > 75] <- "Elder"+ agecat[age >= 55 & age <= 75] <- "Middle Aged"+ agecat[age < 55] <- "Young" })

within()可以認為是數據框版本的with(),將每一行都設置為缺失值,然後按條件賦值(字元型變數,還不是有序因子)。

car包中的recode()函數可以十分簡便的重編碼數值型、字元型向量或因子;doBy包提供了另外一個很受歡迎的函數recodevar();R中自帶了cut()可以將數值型變數切割為多個區間,並返回一個因子。

4.4 變數的重命名

使用 fix() 函數可以彈出「互動式編輯器」方便進行直接更改;

使用編程方式可以使用 names()函數來重命名變數:

> names(leadership)[1] "manager" "date" "country" "gender" "age" "q1" "q2"[8] "q3" "q4" "q5"> names(leadership)[2] <- "testDate"# 也可以用類似的向量方式批量修改> names(leadership)[6:10] <- c("item1", "item2", "item3", "item4", "item5")

plyr包中有一個rename(dataframe,c(oldname="newname",...)函數進行。你可以在plyr獲得更多信息。

4.5 缺失值

R中的字元型缺失值與數值型數據使用的缺失值符號是相同的。缺失值以符號NA(Not Available,不可用)表示。

函數is.na()檢測缺失值是否存在(存在為TRUE)。

> is.na(leadership[,8:10]) q3 q4 q5[1,] FALSE FALSE FALSE[2,] FALSE FALSE FALSE[3,] FALSE FALSE FALSE[4,] FALSE TRUE TRUE[5,] FALSE FALSE FALSE

  • 缺失值是不可比較的,意味著無法使用比較運算符來檢測缺失值是否存在。(即只能使用處理缺失值的函數識別缺失值)
  • 正負無窮是有意義的,用Inf和-Inf標記,因此需要用is.infinite()來判斷,例如:5/0
  • 不可能的值用NaN來標記(Not a number,不是一個數),用is.nan(),例如:sin(Inf)

4.5.1 重編碼某些值為缺失值

> leadership$age[leadership$age == 99] <- NA

需要在分析之前將所有的缺失數據正確的標記為缺失值,才能不影響分析過程。

4.5.2 在分析中排除缺失值

針對大部分函數,可以用na.rm=TRUE參數選項,結果忽略缺失值。

> sum(leadership$q5, na.rm=TRUE)[1] 13> sum(leadership$q5)[1] NA

  • 使用函數na.omit()可以移除所有含有缺失值的觀測。(針對大多數情況慎用)

> na.omit(leadership) manager date country gender age q1 q2 q3 q4 q5 agecat1 1 10/24/08 US M 32 5 4 5 5 5 Young2 2 10/28/08 US F 45 3 5 2 5 5 Young3 3 10/1/08 UK F 25 3 5 5 5 2 Young

4.6 日期值

日期值通常以字元串的形式輸入到R中,然後轉化為以數字形式儲存的日期變數。函數as.Date()用於執行這種妝花,而格式列表如下:

符 號含 義示 例%d數字表示的日期(0~31)01~31%a縮寫的星期名Mon%A非縮寫星期名Monday%m月份(00~12)00~12%b縮寫的月份Jan%B非縮寫月份January%y兩位數的年份07%Y四位數的年份2007

> leadership$date <- as.Date(leadership$date, "%m/%d/%y")

其他的,使用Sys.Date()可以返回當天的日期,而date()則返回當前的日期和時間。

可以使用format來輸出指定格式的日期值,並且提取日期值中的某些部分:

> format(Sys.Date(),"%B %d %Y")[1] "二月 14 2017"> format(Sys.Date(),"%A")[1] "星期二"

R內部儲存的日期是從1970年1月1日開始的天數數字,所以在日期數值上可以進行日期計算(可以使用函數difftime()計算間隔和格式化輸出):

> as.Date("2017-01-01")-as.Date("2016-01-01")Time difference of 366 days> difftime(as.Date("2017-01-01"),as.Date("2016-01-01"),units="weeks")Time difference of 52.28571 weeks

4.6.1 將日期轉換為字元型變數

as.character()可將日期值轉換為字元型

4.6.2 更進一步

lubridate包中包含了許多簡化日期處理的函數,識別、解析、抽取時間和進行複雜運算。

4.7 類型轉換

判 斷轉 換is.numeric()as.numeric()is.character()as.character()is.vector()as.vector()is.matrix()as.matrix()is.data.frame()as.data.frame()is.factor()as.factor()is.logical()as.logical()

> a <- c(1,2,3)> a[1] 1 2 3> is.numeric(a)[1] TRUE> is.vector(a)[1] TRUE> a <- as.character(a)> a[1] "1" "2" "3"> is.numeric(a)[1] FALSE> is.vector(a)[1] TRUE> is.character(a)[1] TRUE

4.8 數據排序

在R中,可以使用order()函數對一個數據框進行排序,默認為升序,如果需要降續使用「-」即可。

> leadership[order(gender, -age),] manager date country gender age q1 q2 q3 q4 q55 5 2009-05-01 UK F 99 2 2 1 2 12 2 2008-10-28 US F 45 3 5 2 5 53 3 2008-10-01 UK F 25 3 5 5 5 24 4 2008-10-12 UK M 39 3 3 4 NA NA1 1 2008-10-24 US M 32 5 4 5 5 5

4.9 數據集的合併

使用merge()函數對兩個數據框進行聯結(內聯結),例:

> total <- merge(dataframeA, dataframeB, by=c("ID","Country"))

如果是簡單的使兩個行數相等的對象橫向聯結,可是使用cbind()進行:

> total <- cbind(A,B)

如果兩個數據框擁有相同的變數,則可以在行上進行合併,使用rbind():

> total <- rbind(dataframeA,dataframeB)

4.10 數據集取子集

4.10.1 選入(保留)變數

數據框中的元素是通過dataframe[row indices,column indices]這樣的記號來訪問的,可以通過這種方法輕鬆的選取變數。如:

> leadership[,c(6:10)] q1 q2 q3 q4 q51 5 4 5 5 52 3 5 2 5 53 3 5 5 5 24 3 3 4 NA NA5 2 2 1 2 1> leadership[c("q1","q2","q3","q4","q5")] q1 q2 q3 q4 q51 5 4 5 5 52 3 5 2 5 53 3 5 5 5 24 3 3 4 NA NA5 2 2 1 2 1

另外利用變數q1、 q2、 q3、 q4和q5組成的向量來選擇,也可以達到選擇的目的,效果等價。

這裡還介紹了用paste("q",1:5,sep="")的方式生成c("q1","q2","q3","q4","q5")的方法。具體的paste()函數會在第5章講解。

4.10.2 剔除(丟棄)變數

> myvars <- names(leadership) %in% c("q3", "q4")> newdata <- leadership[!myvars]> newdata manager date country gender age q1 q2 q51 1 2008-10-24 US M 32 5 4 52 2 2008-10-28 US F 45 3 5 53 3 2008-10-01 UK F 25 3 5 24 4 2008-10-12 UK M 39 3 3 NA5 5 2009-05-01 UK F 99 2 2 1

names(leadership)是包含所有變數名的字元型向量;通過%in% c("q3", "q4"),生成了變數名為"q3"和"q4"的變數為TRUE,其他的為FALSE。

通過第二個命令,選擇了變數名不為TRUE的數據框範圍。

> leadership[c(-8,-9)] # 負數在python中代表倒序查,而在R中代表FALSE> leadership$q3 <- leadership$q4 <- NULL> leadership

可以通過以上兩種方式達到相同的效果,第一種用「-」表示刪掉,第二種將需要刪掉的列定義為NULL(與NA不同)

4.10.3 選入觀測

通過邏輯判斷的方式,選擇需要的內容是數據分析的重要準備工作。

> leadership[1:3,] manager date country gender age q1 q2 q3 q4 q51 1 2008-10-24 US M 32 5 4 5 5 52 2 2008-10-28 US F 45 3 5 2 5 53 3 2008-10-01 UK F 25 3 5 5 5 2

> newdata <- leadership[1:3,]> newdata <- leadership[leadership$gender=="M" &+ leadership$age > 30,]> newdata manager date country gender age q1 q2 q3 q4 q51 1 2008-10-24 US M 32 5 4 5 5 54 4 2008-10-12 UK M 39 3 3 4 NA NA

leadership[1:3]與leadership[1:3,](選取1-3行觀測)的不同在於,leadership[1:3]實質上是leadership[,1:3]的簡寫,選取1-3列變數。

> leadership[c(leadership$date >= as.Date("2009-01-01","%Y-%m-%d") & leadership$date <= as.Date("2009-10-31","%Y-%m-%d")),]> leadership[which(leadership$date >= as.Date("2009-01-01","%Y-%m-%d") & leadership$date <= as.Date("2009-10-31","%Y-%m-%d")),] manager date country gender age q1 q2 q3 q4 q55 5 2009-05-01 UK F 99 2 2 1 2 1> leadership[leadership$date >= as.Date("2009-01-01","%Y-%m-%d") & leadership$date <= as.Date("2009-10-31","%Y-%m-%d"),]

不太理解這裡書中為什麼用which,但是用c的向量也可以達到目的,最簡單的還是什麼都不加也可以...

4.10.4 subset()函數

> newdata <- subset(leadership, age >= 35 | age < 24,select=c(q1, q2, q3, q4))> newdata <- subset(leadership, gender=="M" & age > 25,select=gender:q4)

subset()函數是選取變數非常快捷的方式。選擇方式非常容易理解,而且寫法簡便。

4.10.5 隨機抽樣

sample()函數能夠讓你從數據集中(有放回和無放回的)抽取大小為n的一個隨機樣本:

> mysample <- leadership[sample(1:nrow(leadership), 3, replace=FALSE),]> mysample manager date country gender age q1 q2 q3 q4 q53 3 2008-10-01 UK F 25 3 5 5 5 24 4 2008-10-12 UK M 39 3 3 4 NA NA2 2 2008-10-28 US F 45 3 5 2 5 5

上述抽樣函數的意義為:1到數據框中觀測的數量(總數),抽取的數目和參數:是否放回抽樣(僅從總體中取樣or越取樣本越少)

R中其他的抽樣工具:sampling包(抽取和校正調查樣本);survey包(分析複雜調查數據)

4.11 使用SQL語句操作數據框

使用sqldf包,可以直接使用sqldf()嵌入SQL語句來實現表格的選擇。

> library(sqldf)> newdf <- sqldf("select * from mtcars where carb=1 order by mpg",row.names=TRUE)> newdf

課後練習

> library(DBI)> library(RMySQL)> # 處理需要的日期範圍> con <- dbConnect(MySQL(),host="***",dbname="***",user="***",password="***") > dbSendQuery(con,SET NAMES gbk)<MySQLResult:208334656,9,0>> as.character(Sys.Date()-30,"%Y%m%d")[1] "20170117"> select <- paste("SELECT * from bc_attribute_analysis where 日期>=",as.character(Sys.Date()-30,"%Y%m%d")," and 日期<=",as.character(Sys.Date(),"%Y%m%d")," and 類目=牛仔褲 and 屬性分類=褲長;",sep="")> newdf <- dbGetQuery(con, select)> newdf[1:5,] 日期 類目 屬性分類 屬性 交易指數 支付子訂單數1 2017-01-17 牛仔褲 褲長 七分褲 88217 14692 2017-01-17 牛仔褲 褲長 九分褲 675611 931113 2017-01-17 牛仔褲 褲長 五分褲 14547 1494 2017-01-17 牛仔褲 褲長 短褲 117548 59775 2017-01-17 牛仔褲 褲長 超短褲 21201 271 支付件數 支付買家數1 2190 13742 96071 839453 153 1364 6282 50035 300 252> # 更改標題> names(newdf) <- c("Date","Category","Property","Attribute","Index","Order","No.","Buyer")> newdf$Date <- as.Date(newdf$Date,"%Y-%m-%d")> newdf <- newdf[c(-2,-3)]> newdf <- na.omit(newdf)> # 長褲/九分褲交易指數數據,並做圖分析> # 處理數據> trousers <- newdf[newdf$Attribute == "長褲",1:3]> ninth <- newdf[newdf$Attribute == "九分褲",1:3]> df <- merge(trousers,ninth,by="Date")> names(df) <- c("Date","a","trousers","b","ninth")> df <- df[c(1,3,5)]> # 繪製圖表> opar <- par(no.readonly = TRUE)> par(lwd=2,cex=1.2,font.lab=1,cex.axis=0.8)> plot(df$Date,df$trousers,type = "b",pch=15,lty=1,col="red",ann=FALSE, yaxt="n")> lines(df$Date,df$ninth,type = "b",pch=17,lty=2,col="blue")> title(main="Retail Sales Index",cex.main =1.2,sub="Trousers vs Ninth",xlab="Date",ylab="Sale Index")> axis(2,at=df$trousers,las=2,col="grey",cex.axis=0.5)> legend("topleft",inset=.03,title = "Type",c("Trouser","Ninth"),lty=c(1,2),col=c("red","blue"),pch=c(15,17))> par(opar)


推薦閱讀:

大數據環境下該如何優雅地設計數據分層
泰坦尼克號生存預測(kaggle排名129前2%)
稀土· Meetup| 「碰撞最前沿的圖像識別技術」活動總結
【乾貨】Kaggle 數據挖掘比賽經驗分享
數據分析師什麼時候能不寫SQL了?

TAG:大数据 | 数据分析 | R编程语言 |