如果說R語言學習者會有的書,大概率會有這一本。本書可以說是R語言學習者和使用者的一個分水嶺,在此之前是各種copy調試,在此之後開始用R做一些自己的事情。其實這樣的書可以羅列出好幾本:
- ggplot2 數據分析與圖形藝術(ggplot2 Elegant Graphics for Data Analysis)
- R語言實戰(RinAction)
- R語言核心技術手冊(RinaNutshell)
- R語言數據科學(R for data science)
- 高級R語言編程指南( Advanced R)
這些書每看完一本,都會對R的特性有進一步的理解。《R語言編程藝術》這本書是買的比較早的了,之前也泛泛地翻過,主要是對R的特點有個相對系統的理解。從目錄導圖中不難看出,這本書涉及的內容是廣泛的,如果恰逢其時,你會覺得這本書就是爲當下的你寫的——就像第九十八個階梯,早一步的話望而卻步,晚一步的話只只剩下驀然回首。所以這是一本時長拿來看看的R語言書籍:說不定哪一次就對上號了。
本書的特點主要有:
- 系統知識
- 實例講解
- 擴展案例
- 第七章是這本書的核心
最主要的特點是有大量的演示案例,雖然大部分的主題在 R語言數據科學 或者R語言核心技術手冊均有涉及,但是講述的方法不同,往往樂意無窮《R語言數據科學》這本書像是哈德利·威克漢姆用自己定義的R語言在講述這些知識點(哈德利·威克漢姆重新定義了很多),R語言核心技術手冊又顯得太厚了,讓人向面對 R語言實戰 一樣,望而卻步。
我覺得第七章<R語言編程結構>是這本書的核心,這也許和目前我的水平有關:開始關注函數的實現與組織。這一章探討了編程中的控制結構以及函數的實現,環境作用域等,函數編程的基本概念。在這一章中,我們可以體會到用R語言和會編程其實是兩件事。
像編程這樣的書籍,讀一遍是遠不夠的,因爲我們系要理解的不是人類語言的部分,而是非人的代碼部分,不僅要理解更是要能運用。這也是做紙質書的好處,可以在代碼上做註釋,寫下自己的驚歎和感悟。
另外,本書值得學習的是關於debug的部分,在做調包俠的時候很少用到這項技能,遇到問題找R包換R包安R包,但是如果是自己寫函數了,或者有的R包還不太成熟的話,就需要我們來爲代碼debug。這部分內容,對很多已經是調包俠的人來說是一個進階的突破口。
# class "ut", compact storage of upper-triangular matrices
# utility function, returns 1+...+i
sum1toi <- function(i) return(i*(i+1)/2)
# create an object of class "ut" from the full matrix inmat (0s included)
ut <- function(inmat) {
n <- nrow(inmat)
rtrn <- list() # start to build the object
class(rtrn) <- "ut"
rtrn$mat <- vector(length=sum1toi(n))
rtrn$ix <- sum1toi(0:(n-1)) + 1
for (i in 1:n) {
# store column i
ixi <- rtrn$ix[i]
rtrn$mat[ixi:(ixi+i-1)] <- inmat[1:i,i]
}
return(rtrn)
}
# uncompress utmat to a full matrix
expandut <- function(utmat) {
n <- length(utmat$ix) # numbers of rows and cols of matrix
fullmat <- matrix(nrow=n,ncol=n)
for (j in 1:n) {
# fill j-th column
start <- utmat$ix[j]
fin <- start + j - 1
abovediagj <- utmat$mat[start:fin] # above-diag part of col j
fullmat[,j] <- c(abovediagj,rep(0,n-j))
}
return(fullmat)
}
# print matrix
print.ut <- function(utmat)
print(expandut(utmat))
# multiply one ut matrix by another, returning another ut instance;
# implement as a binary operation
"%mut%" <- function(utmat1,utmat2) {
n <- length(utmat1$ix) # numbers of rows and cols of matrix
utprod <- ut(matrix(0,nrow=n,ncol=n))
for (i in 1:n) { # compute col i of product
# let a[j] and bj denote columns j of utmat1 and utmat2, respectively,
# so that, e.g. b2[1] means element 1 of colument 2 of utmat2
# then column i of product is equal to
# bi[1]*a[1] + ... + bi[i]*a[i]
# find index of start of column i in utmat2
startbi <- utmat2$ix[i]
# initialize vector that will become bi[1]*a[1] + ... + bi[i]*a[i]
prodcoli <- rep(0,i)
for (j in 1:i) { # find bi[j]*a[j], add to prodcoli
startaj <- utmat1$ix[j]
bielement <- utmat2$mat[startbi+j-1]
prodcoli[1:j] <- prodcoli[1:j] +
bielement * utmat1$mat[startaj:(startaj+j-1)]
}
# now need to tack on the lower 0s
startprodcoli <- sum1toi(i-1)+1
utprod$mat[startbi:(startbi+i-1)] <- prodcoli
}
return(utprod)
}
test <- function() {
utm1 <- ut(rbind(1:2,c(0,2)))
utm2 <- ut(rbind(3:2,c(0,1)))
utp <- utm1 %mut% utm2
print(utm1)
print(utm2)
print(utp)
utm1 <- ut(rbind(1:3,0:2,c(0,0,5)))
utm2 <- ut(rbind(4:2,0:2,c(0,0,1)))
utp <- utm1 %mut% utm2
print(utm1)
print(utm2)
print(utp)
}
test()