R是什麼

R,不僅僅是一種語言
本文原載於《程序員》雜誌2010年第8期,因篇幅所限,有所刪減,這裏刊登的是全文,希望對大家有幫助。

R是什麼



工欲善其事,必先利其器,作爲一個戰鬥在IT界第一線的工程師,C/C++、java、perl、python、ruby、php、javascript、erlang等等等等,你手中總有一把使用自如的刀,幫助你披荊斬棘。
應用場景決定知識的儲備與工具的選擇,反過來,無論你選擇了什麼樣的工具,你一定會努力地把它改造成符合自己應用場景所需的那個樣子。從這個道理來說,我選擇了R[1]作爲數據挖掘人員手中攻城陷池的那把雲梯,並努力地把它改造成自己希望的那個樣子。
關於R的一個比較準確的描述是:R是一門用於統計計算和作圖的語言,它不單是一門語言,更是一個數據計算與分析的環境。統計計算領域有三大工具:SAS、SPSS、S,R正是受S語言和Scheme語言影響發展而來。其最主要的特點是免費、開源、各種各樣的模塊十分齊全,在R的綜合檔案網絡CRAN中,提供了大量的第三方功能包,其內容涵蓋了從統計計算到機器學習,從金融分析到生物信息,從社會網絡分析到自然語言處理,從各種數據庫各種語言接口到高性能計算模型,可以說無所不包,無所不容,這也是爲什麼R正在獲得越來越多各行各業的從業人員喜愛的一個重要原因。
從R的普及來看,國外的普及度要明顯好於國內,跟盜版windows的泛濫會影響linux在中國的普及一樣的道理,破解的matlab與SPSS的存在也影響了R在中國的使用人羣。但在國外高校的統計系,R幾乎是一門必修的語言,具有統治性的地位。在工業界,作爲互聯網公司翹楚的google內部也有不少的工程使用R進行數據分析工作,這裏[2]有一個google campus的講課視頻,內容就是用R作爲工具來講述數據挖掘的概念與算法。
隨着近年來R使用者的增加,關於R的報道也屢有見於報端,如2009年初美國紐約時報就有一篇很好的報道:Data Analysts Captivated by R’s Power[3]。報道中述說了R的發展歷史以及由於數據挖掘需求的增長而日益普及的現狀,它雖源於S但其發展卻遠遠地超過了S,已經成爲高校畢業學生所選用的第二大工具語言,google與Pfizer的員工也介紹了R在自己公司中的應用。此外,報道中google首席經濟學家Hal Varian說:R的最讓人驚豔之處在於你可以通過修改它來做所有的事情,而你已經擁有大量可用的工具包,這無疑讓你是站在巨人的肩膀上工作。
以下就R的幾個主要應用場景以及我在實踐中的經驗對這個並不算主流的編程語言作一些介紹。
統計計算:R之最強項
R從它出生的第一天就是爲了做統計計算的,那時它被定義爲一個統計計算與作圖的工具,雖然發展到現在它已經被賦予了越來越強大的功能,但現在R的開發人員裏,還是以各個高校統計系的老師與學生爲主,他們自然最瞭解自己最需要的是什麼。
在統計計算中,我們常常需要根據樣本數據作線性迴歸,得到一定的規律性,R中實現這個功能十分簡單,以下是一個一元線性迴歸的例子:
x <- 1:10
y <- x+rnorm(10, 0, 1)
fit <- lm(y ~ x)
summary(fit)
註明一下,R裏的“<-”符號意義爲賦值,大多數情況下它可以用“=”號來代替,但某些特殊的場合不可以,本文會遵循“<-”這種官方使用的寫法。這個例子的前兩行準備了兩列數據:自變量x與因變量y,第三行的函數lm即根據提供的樣本數據進行線性迴歸計算,得到的模型結果可以用第四行打印出來。函數lm除了可以做這種簡單的一元線性迴歸,還可以做多元線性迴歸,同時返回模型的各種統計量。
做統計的往往免不了要做各種各樣的圖形,R的另一個基本特點就是對圖形的強大支持,以下代碼展示了一個箱線圖的作法,代碼來自boxplot函數的manual,該圖顯示了幾列數據的分位數、中值、均值、奇異點等信息及其對比位置。更詳細的關於R的作圖功能可以參看[4]。
boxplot(mpg~cyl,data=mtcars, main=”Car Milage Data”, xlab=”Number of Cylinders”, ylab=”Miles Per Gallon”)

機器學習:讓你的數據發揮它應有的作用
機器學習、數據挖掘領域面臨着一些抽象自大量現實生活的問題,比如關聯規則挖掘、聚類、分類這三大問題。作爲一個完備的工程計算包,R毫無疑問對它們都提供了足夠的支持。
關聯規則問題源於“買了這件商品的顧客還買了什麼”這個問題,現在已經廣泛應用於客戶行爲分析以及互聯網用戶行爲分析中。關聯規則挖掘領域最經典的算法爲apriori,R的第三方包arules[5],就是專門用於做關聯規則挖掘的。以下例子需要你已經安裝了arules包。
library(arules)
data <- paste(“item1,item2″,”item1″,”item2,item3″, sep=”\n”)
write(data, file = “demo_basket”)
tr <- read.transactions(“demo_basket”, format = “basket”, sep=”,”)
data(“Adult”)
rules <- apriori(Adult, parameter = list(supp = 0.5, conf = 0.9, target = “rules”))
最後一行的apriori函數接受一個transaction對象的輸入,輸出關聯規則對象rules,爲方便起見,這裏用於計算的transaction對象Adult是通過第5行從arules包中現成載入進來的,第2~4行說明了怎麼從一個文本文件中讀入數據並生成一個transaction對象。
聚類算法使用最廣泛的高效算法無疑是kmeans,R在其默認載入的stats包中就包含了這個函數,以下是一個來自kmean說明文檔的例子:
x <- rbind(matrix(rnorm(100, sd = 0.3), ncol = 2), matrix(rnorm(100, mean = 1, sd = 0.3), ncol = 2))
cl <- kmeans(x, 2)
plot(x, col = cl$cluster)
points(cl$centers, col = 1:2, pch = 8, cex=2)
代碼第1行生成兩組兩維的正態分佈的數據,第一組均值爲0,第二組均值爲1,兩組數據方差都爲0.3。第2行對該數據進行聚類,第3和第4行把聚類結果畫出來。
分類器是模式識別領域的研究主題,也是人類認知活動的中心。多年來的學術研究積累下來很多種類型的分類器,而其中比較靠譜的分類器基本都能在R中找到對應的實現。諸多分類器中以svm最爲著名,它也被一些人稱爲是單分類器的王道。以下是一個利用svm對著名的iris數據集進行分類的過程,運行該例子需要你已經安裝了e1071這個包[6]。
library(e1071)
data(iris)
x <- subset(iris, select = -Species)
y <- iris$Species
model <- svm(x, y)
summary(model)
pred <- predict(model, x)
table(pred, y)
第5行代碼調用svm函數,計算由x作爲特徵y作爲類別標籤的分類器模型,第7行把模型應用於原數據進行預測。
以上例子的演示並非想讓各位讀者當場學會各個不同領域中這些功能函數的用法,而是一方面展示一些實際的R代碼以及它解決問題的方式,另一方面說明了R在這些常見的機器學習領域的積累。在R幫助下去解決這些或許不是我們專業的問題,可以省去我們大量重複造輪子的精力,寫出來的代碼也足夠的短小精悍,節省時間之餘也讓你對自己算法邏輯的全局一覽無餘。
高性能計算:向量化與並行/分佈計算
作爲現代數據挖掘人員從業者,可能第一個需要關心的是所使用工具的可伸縮性(scalability),具體來說就是在面對大數據量場景時的計算能力。
一個擁有高性能計算能力的計算包,首先它必須能充分利用歷史上積累下來的那些著名的數值計算包,比如blas、lapack;另一方面,它必須具有良好的可擴展性,即它必須方便開發人員並行化自己的算法,很幸運這些特性R都具備了。
類似於R、scilab與matlab那樣的工程計算包,通常都會以向量化計算(Vectorization)作爲其基本的計算特點(即使python的numpy包也是如此),因爲向量化的處理方式是現代大型計算機的基本特性,在計算機領域,無論硬件還是軟件,都提供了對向量化的支持,硬件上如Intel的MMX, SSE等指令集都提供了對向量化的支持,更多可以看到wikipedia上的介紹[7]。軟件上如blas等著名的計算包,天然地就可以對向量化的命令自動實施並行計算。
所謂向量化,是一種特殊的並行計算的方式,相比於一般程序在同一時間只執行一個操作的方式,它可以在同一時間執行多次操作,通常是對不同的數據執行同樣的一個或一批指令,或者說把指令應用於一個數組/向量。以下列出R中經常使用幾種向量化運算,都是十分稀鬆平常的操作,但它們本質上都是同時對一批數據應用相同的操作,所以都可以經過向量化處理方式的改造:
  • 向量取值,如:V[1:10]
  • 向量賦值,如:V[1:10] <- seq(1,10)
  • lapply,類似於python裏的map函數:lapply(A, mean)
  • 矩陣運算:A + B;A %*% B
向量化因其在計算過程中數據的前後不依賴的特點,是並行計算的天然先驅,一個用向量化實現的算法,必定是一個可以高度並行化的算法。正因爲這個原因,在利用R寫腳本的時候,都要儘量利用向量化的思想來設計自己的算法,儘可能少地使用循環結構。一旦你的程序都是或大都是基於向量化的,除了當時獲得來自於計算機軟硬件上的優化外,將來某一天數據量膨脹使得計算成爲瓶頸時,你就可以極爲方便地把原來的算法並行化。
正如我們所知,CRAN包括了各種你能想像得到的工具包,當然也有不少並行計算的包,這些包被歸納在R高性能計算相關的包列表中[8]。
關於R的向量化及並行計算更詳細的內容可以參考我的一篇博客[9]。
編寫接口與工具包:最有用的包必定是你寫的那一個
一個開源軟件的最強大之處在於大量從業人員的貢獻,R最讓人激奮,進而選擇它作爲工作平臺的一個重要原因則是龐大而無所不包的的CRAN,在那裏幾乎能找到所有你能想像得到的與分析研究相關的工具包,可以說絲毫不遜色於perl的CPAN。之所以擁有一個如此強大的第三方支持,一方面在於R本身在統計計算與計算能力方面的支持,另一方面則在於開發一個R擴展是如此地容易,以致於每一個使用R作爲自己常用工具的人,都會按捺不住強烈的衝動要寫一個自己的包,以滿足工作需要。如果自己的這個包感覺寫得不錯,又爲很多人所需要,就可以提交到CRAN。這是造成CRAN如此龐大的原因,但同時也造成了CRAN的軟件包良萎不全。但大多數情況下,這些包都會是你的得力助手,特別是那些著名而廣爲使用的包,如果覺得它們不滿足你的需要,那麼放心地對它們進行修改吧,因爲它們都是開源的。
下面展示一個簡單的R擴展包的製作過程:
1、生成包結構:新建一個目錄mypkg,同時作爲包名,在mypkg中新建幾個目錄與文件,mypkg的目錄結構如下圖所示。R自帶的函數package.skeleton可以自動幫你生成這些目錄,但它需要一些現成的函數對象或文件作啓動,爲了順序說明整個過程,這裏沒有使用。

2、目錄說明:必需的是DESCRIPTION文件、man目錄和R目錄,剩下的都是可選的。DESCRIPTION文件描述包的meta信息;R目錄下面存放R腳本文件,裏面的函數可導出作爲包函數庫提供給外部使用;如果要在包裏放一些試驗數據,可以放在data目錄裏,常用是以csv格式存放,在R終端裏data(***)可以載入,這裏留空;man目錄是R的幫助文檔,有一定的格式要求,這裏也留空,生成包時會有一些警告,可以不用管;src存放c/c++/fortran源代碼,必須同時放置Makefile或Makevars文件指導編譯程序工作,這裏留空;zzz.R可以在載入包時做一些事情,這裏也留空。
3、添加功能:DESCRIPTION文件的內容可以參考任意一個R包對應文件的寫法,依樣把信息修改成自己相應的信息即可。以下只寫一個簡單的R函數作爲說明,在R目錄下添加一個名爲helloword.R的文件,文件內容如下:
helloword <- function(x, y)
{
return(x*y)
}
4、安裝:在命令行中運行R CMD build mypkg,會編譯生成一個mypkg_0.1.tar.gz安裝包,其中的數字是我在DESCRIPTION裏寫的版本號;運行R CMD INSTALL mypkg,就可以把包安裝到系統裏。
5、試驗:運行R,進入R終端;library(mypkg),載入剛製作的包;search(),可以看到mypkg包已經被載入;在R終端運行helloworld(2,3),返回6,試驗成功。
一個具有一定功能的包就這樣做好了,是不是很簡單。如果有其它需要,只要往R目錄或src目錄添加文件,然後重新生成並安裝就可以了。R與c/c++之間的接口調用也十分方便,限於篇幅,無法更仔細地說明,更詳細的內容可以參考我的幾篇博客[10-13]。
R在中國的發展
R在中國的普及現在並不十分地廣泛,主要還是學校及研究機構在使用,但近年來隨着R的聲名鵲起,也已經有越來越多各個領域的工業界從業人員選擇R作爲自己的工作平臺,其中統計之都[14]是一個國內R用戶的聚焦地。今年的6月份在人民大學舉行了第3屆R語言會議,從前三屆會議的人員組成來看,R的中國用戶羣一直呈現較大的增長趨勢,用戶分佈的領域也越來越豐富。第三屆R語言會議參會者人來源可以從會議紀要中看到[15]。相信隨着數據挖掘廣爲各個公司接受,R也會走近工業界的各行各業中。
R在豆瓣中的應用
有一段時間,我一直在尋找介乎於matlab與系統語言(如C, Fortran)的中間物,希望它既能擁有系統語言的高性能,又能方便數據挖掘人員的日常工作,於是我找到了R,這不僅是一門語言,它更是一個理想的計算環境。它一方面方便我對新算法原型的構建、調試、評測,另一方面並沒有讓我失去系統級語言的計算優勢,甚至在實現並行計算方面擁有了更多的選擇。現在我使用R編寫我們自己的工具包,進行算法原型構造、矩陣運算、並行算法等離線應用,爲相似性計算、推薦系統等上層應用提供底層的支持。
一個R寫的協同過濾推薦的例子
最後用一個R實現的協同過濾推薦的例子來結束本文,協同過濾是推薦系統中一個基本的算法,詳細內容可以參考這裏[16]。由於大量地採用了向量化的計算方式(包括各種矩陣運算),所以算法的實現相當簡潔,有可能是史上代碼最少的協同過濾推薦引擎 data <- read.table(‘data.dat’, sep=’,', header=TRUE)
user <- unique(data$user_id)
subject <- unique(data$subject)
uidx <- match(data$user, user)
iidx <- match(data$subject, subject)
M <- matrix(0, length(user), length(subject))
i <- cbind(uidx, iidx)
M[i] <- 1
mod <- colSums(M^2)^0.5
MM <- M %*% diag(1/mod)
S <- crossprod(MM)
R <- M %*% S
R <- apply(R, 1, FUN=sort, decreasing=TRUE, index.return=TRUE)
k <- 5
res <- lapply(R, FUN=function(r)return(subject[r$ix[1:k]]))
write.table(paste(user, res, sep=’:'), file=’result.dat’,
quote=FALSE, row.name=FALSE, col.name=FALSE)
代碼我就不細加註釋了,有興趣瞭解其原理的同學可以看這裏[16]。
參考:
[1] R官方網站
[2] Youtube上的GoogleTechTalks,通過R來教學數據挖掘:Statistical Aspects of Data Mining (Stats 202)
[3] 紐約時報的報道Data Analysts Captivated by R’s Power
[4] R Graphics
[5] arules package
[6] e1072 package
[7] 向量化
[8] R高性能計算相關的包
[9] 向量化與並行計算
[10] R package的最簡單製作
[11] R與C的接口:從R調用C的共享庫
[12] R對象結構,用.Call的調用方式更靈活地寫R-package
[13] 編寫R包C擴展的核心指引
[14] 統計之都
[15] 第三屆R語言會議(北京會場)會議紀要
[16] 可能是史上代碼最少的協同過濾推薦引擎

發佈了32 篇原創文章 · 獲贊 6 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章