《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()等第一章提到過的語句保存為不同形式的圖形。
繪製多個圖形,後面的圖形會覆蓋掉先前的圖形,如何才能創建多個圖形並隨時查看每一個,這裡有三個方法:
- 方法一:通過dev.new()創建新的窗口,繪製圖形,然後再次創建
- 方法二:勾選「歷史」History -> 「記錄」Recording 通過 「上一個」Previous和「下一個」Next查看已經繪製的圖形。
- 方法三:可以使用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類函數
- 函數功能:多個圖形設備之間提供控制功能。
- 使用方式:
- 所有關於圖形的操作都在一個設備中進行,即僅有一個設備是「活躍設備」;
- 「空設備」null device 總是打開並佔位;
- 任何使用空設備的操作,會導致另外一個設備被打開,一旦有其他設備被打開,則空設備不再活躍;
- 設備有格子的名字,同時有編號(1到63);
- 空設備的編號始終為1;
- dev.list() 返回打開的設備的名單列表,但不包括空設備;
- dev.off() 關閉指定設備(預設狀態下為當前活躍設備);
- 關閉後,其他打開設備變為活躍;
- 關閉後,返回新打開的活躍設備的名字和編號;
- 設備1不能被關閉,即對設備1的關閉操作是錯誤的;
- graphics.off() 關閉所有打開的設備;
- dev.set() 指定一個特定的設備為活躍;
- 若無指定,相當於dev.next();
- 若指定為1,打開新的設備並設為活躍,返回新設備的名字和編號;
- dev.new() 打開一個新的設備。R經常根據需要自動打開新的設備,但使用命令可以跨平台打開更多設備;返回新設備名字和編號;
- dev.cur() 查看當前的活躍設備,返回當前活躍設備的名字和編號的向量,返回1即空設備;
- dev.next() 查看緊隨當前活躍進程的下一個進程,返回其名字和編號;
- 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了?