《R語言實戰(zhàn)》學習筆記及代碼(第五章)

感謝Robert I.Kabacoff 著作本書,同時感謝高濤、肖楠、陳鋼編譯此書。

最近在學習《R語言實戰(zhàn)》,特將學習過程記錄下來,供各位朋友參考,雖說是筆記,但是90%是書中內(nèi)容,另外10%是自己偶爾冒出的一點點想法的記錄和一些疑問,希望互相探討。末尾有本章的代碼清單下載地址,與各位交流,還是提倡按照書中內(nèi)容把代碼一個個敲出來。

第五章  高級數(shù)據(jù)管理

本章內(nèi)容

數(shù)學和統(tǒng)計函數(shù)

字符處理函數(shù)

循環(huán)和條件執(zhí)行

自編函數(shù)

數(shù)據(jù)整合與重塑



5.1  一個數(shù)據(jù)處理難題

一個難題:

  1. 三科成績是無法比較的。
  2. 需要一種方法來確定某個學生在前述得分上百分比排名。
  3. 表示姓名的字段只有一個,需要將姓和名拆開。



5.2  數(shù)值和字符處理函數(shù)

本節(jié)將學習R中作為數(shù)據(jù)處理基石的函數(shù),它們可分為數(shù)值(數(shù)學、統(tǒng)計、概率)函數(shù)和字符處理函數(shù)。



5.2.1  數(shù)學函數(shù)

書中表5-2列出了常用的數(shù)學函數(shù)和簡短的用例。(P83頁)

值得一提的是round(x, digits = n) 表示將x舍入為指定位的小數(shù)

signif(x, digits = n)表示將x舍入為指定的有效數(shù)字位數(shù)

對比如下

round(3.475, digits = 2)返回值為3.48。(保留兩位小數(shù))

signif(3.475, n= = 2)返回值為3.5。(保留兩位有效數(shù)字)

表5-2中的示例將數(shù)學函數(shù)應用到了標量(單獨的數(shù)值)上。當這些函數(shù)被應用于數(shù)值向量、矩陣或者數(shù)據(jù)框時,它們會作用于其中每一個獨立的值,然后重新生成一個向量、矩陣或數(shù)據(jù)框。



5.2.2  統(tǒng)計函數(shù)

方差:表示點的離散程度。方差越小,離散程度越低,越接近平均值。公式表達為:
S=[ (x1-x)^2+(x2-x)^2+(x3-x)^2+……+(xn-x)^2]

標準差是方差開根號。

什么是絕對中位差、分位數(shù)、值域、滯后差分、進化中心化、標準化?

代碼清單5-1  均值和標準差的計算

x <- c(1, 2, 3, 4, 5, 6, 7, 8)

簡潔的方式

mean(x)

sd(x)

冗長的方式

n <- length(x)

meanx <- sum(x)/n

css <- sum((x - meanx)^2)

sdx <- sqrt(css / (n-1))

meanx

sdx

第二種方式中修正平方和(css)的計算過程是很有啟發(fā)性的:

(1) x等于c(1, 2, 3, 4, 5, 6, 7, 8),x的平均值等于4.5(length(x)返回了x中元素的數(shù)量):

(2) (x - meanx)從x中的每個元素中減去了4.5,結果為c(-3.5, -2.5, -1.5, -0.5, 0.5, 1.5, 2.5, 3.5)

(3) (x - meanx)^2將(x - meanx)的每個元素求平方,結果為c(12.25, 6.25, 2.25, 0.25, 0.25, 2.25, 6.25, 12.25)

(4) summ((x - meanx)^2)對((x - meanx)^2)的所有元素求和,結果為42。

數(shù)據(jù)的標準化

將一組數(shù)據(jù),投射到很小區(qū)間內(nèi)的方法,便于分析。標準化之后的數(shù)據(jù)有這樣的特征:均值為0,標準差為1。

函數(shù)scale()對矩陣或數(shù)據(jù)框的制定了進行均值為0,標準差為1的標準化。

newdata <- scale(mydata

要對每一列進行任意均值和標準差的標準化,可以使用如下代碼:

newdata <- scale(mydata) * SD + M

其中SD表示想要的標準差,M表示想要的均值。注意,在非數(shù)值型的列上用scale()函數(shù)會報錯。如果要對指定列而不是整個數(shù)據(jù)框或矩陣進行標準化,可以使用如下代碼:

newdata <- transform(mydata, myvar = scale(myvar) * 10 + 50)

此句將變量myvar標準化為均值50、標準差為10的變量。

問:是否有能將數(shù)據(jù)落到指定區(qū)間的方法?這種方法與書中的“指定均值和標準差”的方法有何異同?



5.2.3  概率函數(shù)

概率函數(shù)通常用來生成特征已知的模擬數(shù)據(jù),以及在用戶編寫的統(tǒng)計函數(shù)中計算概率值。在R中,概率函數(shù)形如:
[dpqr]distribution_abbreviation()

其中第一個字母表示其所指分布的某一方面:

d = 密度函數(shù)(density)

p = 分布函數(shù)(distribution function)

q = 分位數(shù)函數(shù)(quantile function)

r = 生成隨機數(shù)(隨機偏差)

1. 設定隨機數(shù)種子

每次生成偽隨機數(shù)的時候,函數(shù)都會使用一個不同的種子,可以通過函數(shù)set.seed()顯式指定這個種子,讓結果可以重現(xiàn)(reproducible)。代碼清單5-2給出了一個示例,這里的函數(shù)runif()用來生成0到1區(qū)間上服從均勻分布的偽隨機數(shù)。

設置種子之后,如果種子是同一個數(shù),那么每次產(chǎn)生的隨機數(shù),求和、均值、標準差都相同。這幾個參數(shù)與種子數(shù)之間有什么關系?

注意:如果需要設定種子,那么在每一次生成隨機數(shù)之前都要設定

2. 生成多元正態(tài)數(shù)據(jù)

蒙特卡洛方法:也稱統(tǒng)計模擬方法,是以概率統(tǒng)計理論為指導的一類非常重要的數(shù)值計算方法。是指使用隨機數(shù)(或更常見的偽隨機數(shù))來解決很多計算問題的方法。與它對應的是確定性算法。蒙特卡洛方法百度百科解釋

MASS包可以讓獲取來自給定均值向量和協(xié)方差陣的多元正態(tài)分布的數(shù)據(jù)變得更容易。調用格式為:

mvrnorm(n, mean, sigma)

其中n是你想要的樣本大小,mean為均值向量,而sigma是方差-協(xié)方差矩陣(或相關矩陣)。



5.2.4  字符處理函數(shù)

書中P89-P90頁,表5-6 給出了字符處理函數(shù)表。

請注意,函數(shù)grep()、sub()和strsplit()能夠搜索某個文本字符串(fixed = TRUE)或者某個正則表達式(fixed = FALSE,默認值為FALSE)。正則表達式為文本模式的匹配提供了一套清晰而簡練的語法。正則表達式 - 語法或者正則表達式語法

例如^[hc]?at

可以匹配任意0個或1個以h或c開頭、后接at的字符串。因此,此表達式可以匹配hat、cat和at,但不會匹配bat。



5.2.5  其他實用函數(shù)

轉義符“\”,\n表示新行,\t為制表符,'為單引號,\b為退格。



5.2.6  將函數(shù)應用于矩陣和數(shù)據(jù)框

R函數(shù)的諸多有趣特性之一就是他們可以應用到一系列的數(shù)據(jù)對象上,包括向量、標量、矩陣、數(shù)組和數(shù)據(jù)框。

R中提供了一個apply()函數(shù),可將一個任意函數(shù)“應用”到矩陣、數(shù)組、數(shù)據(jù)框的任何維度上。其格式為:

apply(x, MARDIN, FUN, …)

其中,x為數(shù)據(jù)對象,MARGIN是維度的下標,F(xiàn)UN是由你指定的函數(shù),而…則包含了想傳遞給FUN的參數(shù)。在矩陣或數(shù)據(jù)框中,MARGIN=1表示行,MARGIN=2表示列。

mydata <- matrix(rnorm(30), nrow = 6)

mydata

apply(mydata, 1, mean)

apply(mydata, 2, mean)

apply(mydata, 2, mean, trim =0.2)

最后一行表示計算每一列的截尾均值,忽略了最高和最低的20%

apply()可把函數(shù)應用到數(shù)組的某個維度上,而lapply()和aspply()則可將函數(shù)應用到列表(list)上。



5.3  數(shù)據(jù)處理難題的一套解決方案

針對5.1節(jié)提出的問題,本節(jié)給出了一個解決方案。

  1. options(digits = 2)
  2. Student <- c("John Davis", "Angela Williams", "Bullwinkle Moose", "David Jones", "Janice Markhammer", "Cheryl Cushing", "Reuven Ytzrhak", "Greg Knox", "Joel England","Mary Rayburn")
  3. Math <- c(502, 600, 412, 358, 495, 512, 410, 625, 573, 522)
  4. Science <- c(95, 99, 80, 82, 75, 85, 80, 95, 89, 86)
  5. English <- c(25, 22, 18, 15, 20, 28, 15, 30, 37, 18)
  6. roster <- data.frame(Student, Math, Science, English, stringsAsFactors = FALSE)
  7. z <- scale(roster[ , 2:4])
  8. score <- apply(z, 1, mean)
  9. roster <- cbind(roster, score)
  10. y <- quantile(score, c(0.8, 0.6, 0.4, 0.2))
  11. y
  12. roster$grade[score >= y[1]] <- "A"
  13. roster$grade[score < y[1] & score >= y[2]] <- "B"
  14. roster$grade[score < y[2] & score >= y[3]] <- "C"
  15. roster$grade[score < y[3] & score >= y[4]] <- "D"
  16. roster$grade[score < y[4]] <- "F"
  17. name <- strsplit((roster$Student), " ")
  18. name
  19. lastname <- sapply(name, "[", 2)
  20. firstname <- sapply(name, "[", 1)
  21. roster <- cbind(firstname, lastname, roster[, -1])
  22. roster <- roster[order(lastname, firstname),]
  23. roster

以下是解讀過程:

  1. 限定了輸出小數(shù)點后數(shù)字的位數(shù),并且讓輸出更容易閱讀。

  2. 輸入學生姓名。

  3. 輸入數(shù)學成績。

  4. 輸入科學成績。

  5. 輸入英語成績。

  6. 創(chuàng)建一個數(shù)據(jù)框roster,其中的變量分別是:姓名、數(shù)學成績、科學成績、英語成績。

  7. 將數(shù)據(jù)框roster的第二到四列標準化,并保存到z中。標準化的原因是:由于數(shù)學、科學、和英語考試得到分值不同(均值和標準差相去甚遠),在組合之前需要讓他們變得可以比較。標準化就是讓每科的成績都用單位標準差來表示,而不是以原始的尺度來表示了。

  8. 求z中所有行的均值,并保存到score中。

  9. 將roster和score按列合成為一個矩陣,保存到roster中。

  10. 分別求score的20%分位數(shù),40%分位數(shù),60%分位數(shù),80%分位數(shù)。

  11. 查看score的20%分位數(shù),40%分位數(shù),60%分位數(shù),80%分位數(shù)。分別是
    80% : 0.91
    60% : 0.32
    40% : -0.36
    20% : -0.88

  1. 將大于等于80%,即大于等于0.91的成績評為A。

  2. 將60%(包含)至80%(不包含),即位于0.32(包含)和0.91(不包含)之間的成績,評為B。

  3. 將40%(包含)至60%(不包含),即位于-0.36(包含)和0.32(不包含)之間的成績,評為C。

  4. 將20%(包含)至40%(不包含),即位于-0.88(包含)和-0.36(不包含)之間的成績,評為D。

  5. 將小于20%,即小于-0.88的成績評為F。

  6. 使用strsplit()函數(shù),將原數(shù)據(jù)框中的姓名,按照空格分成兩列,并保存到新的列表name中。

  7. 查看新列表name。

  8. 選取列表中第二列,保存到一個新變量lastname中。

  9. 選取列表中第一列,保存到一個新變量firstname中。

  10. 將firstname和lastname添加到花名冊roster中,并將原本第一個變量Student刪除,(roster[, -1])。

  11. 使用order()函數(shù)依照firstname和lastname對數(shù)據(jù)框進行排序。

  12. 查看數(shù)據(jù)框roster。



5.4  控制流

為了理解貫穿本節(jié)的語法示例,請牢記以下概念:

語句(statement)是一條單獨的R語句或一組符合語句(包含在花括號{}中的一組R語句,使用分號分隔);

條件(cond)是一條最終被解析為真(TRUE)或假(FALSE)得表達式;

表達式(expr)是一條數(shù)值或字符串的求值語句;

序列(seq)是一個數(shù)值或字符串序列。



5.4.1  重復和循環(huán)

循環(huán)結構重復地執(zhí)行一個或一系列語句,知道某個條件不為真為止。循環(huán)結構包括for和while結構。

1.  for結構

for循環(huán)重復地執(zhí)行一個語句,直到某個變量不包不再包含在序列seq中為止。語法為:

for(var in seq) statement

在下例中:

for (i in 1:10) print ("Hello")

單詞Hello被輸出了10次。

2.  while結構

while循環(huán)重復地執(zhí)行一個語句,直到條件不為真為止。語法為“

while (cond) statement

第二個例子,代碼:

i <- 10

while (i < 0) {pirnt ("Hello"); i <- i - 1}

請確保括號內(nèi)while的條件語句能夠改變,即讓它在某個時刻不再為真——否則循環(huán)將永不停止!



5.4.2  條件執(zhí)行

在條件執(zhí)行結構中,一條或一組語句僅在滿足一個指定條件時執(zhí)行。條件執(zhí)行結構包括if-else、ifelse和switch。

1.  if-else結構

控制結構if-else在某個給定條件為真時執(zhí)行語句。也可以同時在條件為假時執(zhí)行另外的語句,語法為:

if (cond) statement

if (cond) statement1 else statement2

示例如下:

if (is.character(grade)) grede <- as.factor(grade)

當grade為字符型向量時,將其轉化為因子。

if (!is.factor(grade)) grade <- as.factor else print ("Grade already is a factor")

當grade不是因子時,將其轉化為因子,當其是因子是,輸出一段信息。

2.  ifelse結構

ifelse是if-else比較緊湊的向量化結構。語法為:

ifelse (cond, statement1, statement2)

當條件為真時,執(zhí)行第一條語句,當條件為假時,執(zhí)行第二條語句。

示例如下:

ifelse (score > 0.5, print("Passed"), print("Failed"))

outcome <- ifels (score > 0.5, "Passed", "Failed")

3.  switch結構

switch根據(jù)一個表達式的值選擇語句執(zhí)行。語法如下:

switch(expr, …)

其中的…表示與expr的各種可能輸出值綁定的語句。



5.5  用戶自編函數(shù)

R最大的優(yōu)點之一就是用戶可以自行添加函數(shù)。R中許多函數(shù)都是由已有函數(shù)構成的。一個函數(shù)的結構看起來大致如此:

myfunction <- function(arg1, arg2, …){

  statements

  return(object)

  }

在第二個自編函數(shù)的示例中,函數(shù)cat()僅會在輸入的日期格式類型不匹配“l(fā)ong”或“short”時執(zhí)行。使用一個表達式來捕獲錯誤輸入的參數(shù)值通常是一個好主意

有若干函數(shù)可以用來為函數(shù)添加錯誤捕獲和糾正功能。warning()可以生成一條錯誤提示信息。message()可以生成一條診斷信息。stop()可以停止當前表達式的執(zhí)行并提示錯誤。

小提示

一旦開始編寫無論任何長度和復雜度的函數(shù),優(yōu)秀調試工具的重要性都會凸顯出來。R中有許多實用的內(nèi)建調試函數(shù),也有許多用戶貢獻包提供了額外的功能。

關于這個話題,一份優(yōu)秀的參考資料是Duncan Murdoch整理的“Debugging in R”



5.6  整合與重構

在整合數(shù)據(jù)時,往往將多組觀測替換為根據(jù)這些觀測計算的描述性統(tǒng)計量。在重塑數(shù)據(jù)時,則會通過修改數(shù)據(jù)的結構(行和列)來決定數(shù)據(jù)的組織方式。



5.6.1  轉置

轉置(反轉行和列)也許是重塑數(shù)據(jù)集的眾多方法種最簡單的一個了。使用函數(shù)t()即可對一個矩陣或者數(shù)據(jù)框進行轉置。對于后者,行名將成為變量(列)名。



5.6.2  整合數(shù)據(jù)

在R中使用一個或多個by變量和一個預先定義好的函數(shù)來折疊(collapse)數(shù)據(jù)時比較容易得多。其調用格式為:

aggregate(x, by, FUN)

其中x是待折疊的數(shù)據(jù)對象,by是一個變量名組成的列表,這些變量將被去掉以形成新的觀測,而FUN則是用來計算描述性統(tǒng)計量的標量函數(shù),它將用來計算新觀測中的值。

5.6.3  reshape包

首先將數(shù)據(jù)“融合”(melt),以使每一行都是一個唯一的標識符-變量組合。然后將數(shù)據(jù)“重鑄”為你想要的任何形狀。在重鑄過程中你可以使用任何函數(shù)對數(shù)據(jù)進行整合。

在這個數(shù)據(jù)集中,測量(measurement)是指最后兩列中的值(5、6、3、5、6、1、2、4)。每個測量都能夠被標識符(在本例中,標識符是指ID、Time以及觀測屬于X1還是X2)唯一地確定。

1.  融合

使用以下代碼:

install.package("reshape")

library(reshape)

md <- melt(mydata, id = (c("id", "time")))

2.  重鑄

cast()函數(shù)讀取已融合的數(shù)據(jù),并使用你提供的公式和一個(可選的)用于整合數(shù)據(jù)的函數(shù)將其重塑。調用格式為:

newdata <- cast(md, formula, FUN)

其中的md為已融合的數(shù)據(jù),formula描述了想要的最后結果,而FUN是(可選的)數(shù)據(jù)整合函數(shù)。其接受公式形如:

rowvar1 + rowvar2 + … + ~ colvar1 + colvar2 + …

在這一公式中,rowvar1 + rowvar2 + … 定義了要劃掉的變量集合,以確定各行的內(nèi)容,而colvar1 + colvar2 + … 則定義了要劃掉的、確定各列內(nèi)容的變量集合。





<font color=gray size=3 face="微軟雅黑">作者注:本節(jié)(5.6.3)由于第一個示例代碼就無法得到書中的結果,所以,本節(jié)學習筆記實際上只摘取了書中的內(nèi)容,未理解其中的意義。主要是由于示例的表5-8 不知道何種形式的數(shù)據(jù)集,書中未給出,在嘗試了矩陣、數(shù)據(jù)框、列表創(chuàng)建相同內(nèi)容的數(shù)據(jù)集之后,均失敗。</font>

附件:《R語言實戰(zhàn)》學習筆記及代碼(第五章)

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,030評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,310評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,951評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,796評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,566評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,055評論 1 322
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,142評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,303評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,799評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,683評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,899評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,409評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,135評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,520評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,757評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,528評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,844評論 2 372

推薦閱讀更多精彩內(nèi)容