2014年6月12日 星期四

[R][翻譯] apply、sapply、lapply之區別

原文:Using apply, sapply, lapply in R
        R和一般程式語言或統計軟體的不同在於進行迴圈運算時,可以使用向量的方式來處理,也就是本文主要要介紹的apply、sapply和lapply。這三個功能相似,卻有一點不同,今天無意中發現一篇好文章在比較這三者,因此將原文翻譯並摘要後與大家分享。


本文範例使用的DATA:
        method1  method2    method3 
[1,] 0.05517714 0.014054038 0.017260447
[2,] 0.08367678 0.003570883 0.004289079
[3,] 0.05274706 0.028629661 0.071323030
[4,] 0.06769936 0.048446559 0.057432519
[5,] 0.06875188 0.019782518 0.080564474 
[6,] 0.04913779 0.100062929 0.102208706

要產生上述DATA請參考下方:

m <- matrix(data=cbind(rnorm(30, 0), rnorm(30, 2), rnorm(30, 5)), nrow=30, ncol=3)

Apply


apply是將一個公式或函數(第三個參數)套用在某個資料集(第一個參數)中的每個元素上,特別的是,可以用第二個參數來指定公式是要依照ROW還是COL來執行。


--當第二個參數是1時,公式by row來執行
apply(m, 1, mean)
# [1] 2.408150 2.709325 1.718529 0.822519 2.693614 2.259044 1.849530 2.544685 2.957950 2.219874
#[11] 2.582011 2.471938 2.015625 2.101832 2.189781 2.319142 2.504821 2.203066 2.280550 2.401297
#[21] 2.312254 1.833903 1.900122 2.427002 2.426869 1.890895 2.515842 2.363085 3.049760 2.027570

--當地二個參數是2時,公式by col執行
apply(m, 2, mean)
#[1] -0.02664418  1.95812458  4.86857792

Our own functions


我們也可以在apply中定義自己的function:

apply(m, 2, function(x) length(x[x<0]))
#[1] 14  1  0

上面這個fun的主要目的是計算m這個DATA中,每一欄小於零的項目個數,
function(x)的部分就是用m來代入。


我們也可以用下列的方式來檢視每一欄中有沒有矩陣(matrix)
apply(m, 2, function(x) is.matrix(x))
#[1] FALSE FALSE FALSE

看看有沒vec
apply(m, 2, is.vector)
#[1] TRUE TRUE TRUE

當我們要計算小於零的項次時,一定要將公式包在function(x)裡面,不然R會找不到x
apply(m, 2, length(x[x<0]))
#Error in match.fun(FUN) : object 'x' not found

apply(m, 2, function(x) mean(x[x>0]))
#[1] 0.4466368 2.0415736 4.8685779

Using sapply and lapply


sapply和lapply是兩兄弟,都會將公式帶入到輸入檔案的每個元素上,差別在於:
sapply吐回一個vactor
lapply吐回一個list

sapply(1:3, function(x) x^2)
#[1] 1 4 9



lapply(1:3, function(x) x^2)
#[[1]]
#[1] 1
#
#[[2]]
#[1] 4
#
#[[3]]
#[1] 9

我們也可以透過參數 simplify=FALSE 讓sapply吐回一個list

sapply(1:3, function(x) x^2, simplify=F)
#[[1]]
#[1] 1
#
#[[2]]
#[1] 4
#
#[[3]]
#[1] 9

或是在lapply裡使用 unlist 參數讓lapply吐回一個vector

unlist(lapply(1:3, function(x) x^2))
#[1] 1 4 9



Dirty Deeds


回到一開始的DATA,對於一個矩陣,要如何用sapply或lapply計算欄位平均數呢?

sapply(1:3, function(x) mean(m[,x]))
[1] -0.02664418  1.95812458  4.86857792

我們使用欄位index(1:3)的方式代入到function中,並且使用[,x]的方式來指定針對欄來做計算。


我們可以將上述function中的m,用y來取代,變成一個有兩個變數的function,x部分一樣是第一個參數中的1:3,y在之後再用m來指定代入。

sapply(1:3, function(x, y) mean(y[,x]), y=m)
#[1] -0.02664418  1.95812458  4.86857792

這篇文章對於apply、sapply、lapply的用法講得非常容易了解,再此介紹給各位。

p.s.沒看過這篇文章以前,如果要計算欄位平均數,我都直接用sqldf安定XD
現在多會一種方式,而且比SQLDF看來簡單(?)