1. 程式人生 > >R語言學習筆記之apply、lapply、sapply、mapply、tapply函式詳解

R語言學習筆記之apply、lapply、sapply、mapply、tapply函式詳解

轉載於:http://blog.csdn.net/wa2003/article/details/45887055

R語言提供了批量處理函式,可以迴圈遍歷某個集合內的所有或部分元素,以簡化操作。

這些函式底層是通過C來實現的,所以效率也比手工遍歷來的高效。
批量處理函式有很重要的apply族函式:lapply sapply apply tapply mapply。apply族函式是高效能計算的運算向量化(Vectorization)實現方法之一,比起傳統的for,while常常能獲得更好的效能。
    apply : 用於遍歷陣列中的行或列,並且使用指定函式來對其元素進行處理。
    lapply : 遍歷列表向量內的每個元素,並且使用指定函式來對其元素進行處理。返回列表向量。
    sapply : 與lapply基本相同,只是對返回結果進行了簡化,返回的是普通的向量。
    mapply: 支援傳入兩個以上的列表。  

   tapply: 接入引數INDEX,對資料分組進行運算,就和SQL中的by group一樣。

(1)行或列遍歷操作函式apply

 apply(X, MARGIN, FUN, ...)
     
引數:

       X: an array, including a matrix.

  MARGIN: 1:行操作; 2:列操作

 FUN:函式名

用apply可以很方便地按行列求和/平均,其結果與colMeans,colSums,rowMeans,rowSums是一樣的。

舉例如下:

> a<-matrix(1:12,c(3,4))
> a
     [,1] [,2] [,3] [,4]
[1,]    1    4    7   10
[2,]    2    5    8   11
[3,]    3    6    9   12
> apply(a,1,sum)
[1] 22 26 30
> apply(a,2,sum)
[1]  6 15 24 33
> apply(a,1,function(x) sum(x)+2)
[1] 24 28 32
> apply(a,1,function(x) x^2)
     [,1] [,2] [,3]
[1,]    1    4    9
[2,]   16   25   36
[3,]   49   64   81
[4,]  100  121  144

(2)列表(list)遍歷函式lapply

lapply(list, function, ...)
特點:對每列進行操作,非常適合資料框;輸入的資料必須是list型。

> a<-matrix(1:12,c(3,4))
> a
     [,1] [,2] [,3] [,4]
[1,]    1    4    7   10
[2,]    2    5    8   11
[3,]    3    6    9   12
> a.df<-data.frame(a)
> a
     [,1] [,2] [,3] [,4]
[1,]    1    4    7   10
[2,]    2    5    8   11
[3,]    3    6    9   12
> is.list(a.df)
[1] TRUE
> str(a.df)
'data.frame':    3 obs. of  4 variables:
 $ X1: int  1 2 3
 $ X2: int  4 5 6
 $ X3: int  7 8 9
 $ X4: int  10 11 12
> lapply(a.df, function(x) x+3)
$X1
[1] 4 5 6
$X2
[1] 7 8 9
$X3
[1] 10 11 12
$X4
[1] 13 14 15
> lapply(a.df, function(x) sum(x)+3)
$X1
[1] 9
$X2
[1] 18
$X3
[1] 27
$X4
[1] 36
> y<-lapply(a.df, function(x) sum(x)+3)
> is.list(y)
[1] TRUE
> names(y)
[1] "X1" "X2" "X3" "X4"
> y
$X1
[1] 9
$X2
[1] 18
$X3
[1] 27
$X4
[1] 36
> y[1]
$X1
[1] 9
> y[[1]]
[1] 9
> y$X1
[1] 9

(3)sapply

sapply(list, function, ..., simplify)
simplify=F:返回值的型別是list,此時與lapply完全相同
simplify=T(預設值):返回值的型別由計算結果定,如果函式返回值長度為1,則sapply將list簡化為vector;
如果返回的列表中每個元素的長度都大於1且長度相同,那麼sapply將其簡化位一個矩陣



> yy<-sapply(a.df, function(x) x^2)
> yy
     X1 X2 X3  X4
[1,]  1 16 49 100
[2,]  4 25 64 121
[3,]  9 36 81 144
> str(yy)
 num [1:3, 1:4] 1 4 9 16 25 36 49 64 81 100 ...
 - attr(*, "dimnames")=List of 2
  ..$ : NULL
  ..$ : chr [1:4] "X1" "X2" "X3" "X4"
> str(y)
List of 4
 $ X1: num 9
 $ X2: num 18
 $ X3: num 27
 $ X4: num 36

> yy<-sapply(a.df, function(x,y) x^2+y, y=3)
> yy
     X1 X2 X3  X4
[1,]  4 19 52 103
[2,]  7 28 67 124
[3,] 12 39 84 147> y1<-sapply(a.df, sum)
> y1
X1 X2 X3 X4 
 6 15 24 33 
> str(y1)
 Named int [1:4] 6 15 24 33
 - attr(*, "names")= chr [1:4] "X1" "X2" "X3" "X4"
> y1<-sapply(a.df, sum,simplify=F)
> y1
$X1
[1] 6

$X2
[1] 15

$X3
[1] 24

$X4
[1] 33

> str(y1)
List of 4
 $ X1: int 6
 $ X2: int 15
 $ X3: int 24
 $ X4: int 33

(4)mapply:mapply是sapply的多變數版本(multivariate sapply),Apply a Function to Multiple List or Vector  Arguments

mapply(FUN, ..., MoreArgs = NULL, SIMPLIFY = TRUE, USE.NAMES = TRUE)

> mapply(function(x,y) x^y, c(1:5), c(1:5))
[1]    1    4   27  256 3125
> a<-matrix(1:12,c(3,4))
> a
     [,1] [,2] [,3] [,4]
[1,]    1    4    7   10
[2,]    2    5    8   11
[3,]    3    6    9   12
> mapply(sum, a[,1],a[,3],a[,4])
[1] 18 21 24

> mapply(function(x,y,z) x^2+y+z, a[,1],a[,3],a[,4])
[1] 18 23 30

(5) tapply(X, INDEX, FUN = NULL, ..., simplify = TRUE)

x是需要處理的向量,INDEX是因子(因子列表),FUN是需要執行的函式,simplify指是否簡化輸入結果(考慮sapply對於lapply的簡化)

補充個因子函式gl,它可以很方便的產生因子,在方差分析中經常會用到 

> gl(3,5)                 3是因子水平數,5是重複次數
 [1] 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3
Levels: 1 2 3
> gl(3,1,15)                 15是結果的總長度
 [1] 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
Levels: 1 2 3

>  df <- data.frame(year=kronecker(2001:2003, rep(1,4)), loc=c('beijing','beijing','shanghai','shanghai'), type=rep(c('A','B'),6), sale=rep(1:12))
> df
   year      loc type sale
1  2001  beijing    A    1
2  2001  beijing    B    2
3  2001 shanghai    A    3
4  2001 shanghai    B    4
5  2002  beijing    A    5
6  2002  beijing    B    6
7  2002 shanghai    A    7
8  2002 shanghai    B    8
9  2003  beijing    A    9
10 2003  beijing    B   10
11 2003 shanghai    A   11
12 2003 shanghai    B   12
> tapply(df$sale,df[,c('year','loc')],sum)
      loc
year   beijing shanghai
  2001       3        7
  2002      11       15
  2003      19       23
> tapply(df$sale,df[,c('type','loc')],sum)
    loc
type beijing shanghai
   A      15       21
   B      18       24