R語言中的循環函數(Grouping Function)


R語言中有幾個常用的函數,可以按組對數據進行處理,apply, lapply, sapply, tapply, mapply,等。這幾個函數功能有些類似,下面介紹下這幾個函數的用法。

Apply

這是對一個Matrix或者Array進行某個維度的運算。其格式是:

Apply(數據,維度Index,運算函數,函數的參數)

對於Matrix來說,其維度值為2,第二個參數維度Index中,1表示按行運算,2表示按列運算。下面舉一個例子:

m<-matrix(1:6,2,3)

構建一個簡單的2行3列的矩陣,內容為:

     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6
如果我們要計算每一行的sum值,那么我們可以寫為:
apply(m,1,sum)
[1]  9 12
如果要計算每一列的mean值,那么改為:
apply(m,2,mean)
[1] 1.5 3.5 5.5
假如某個值為NA,那么要忽略NA值,進行每一行的SUM怎么辦呢?
m[2,2]<-NA
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2   NA    6
apply(m,1,sum)
[1]  9 NA
本身sum函數有一個參數na.rm,我們可以將這個參數帶人到apply函數中,作為第4個參數:
apply(m,1,sum,na.rm=TRUE)
[1] 9 8
需要注意的是如果是Data Frame,那么系統會將其轉為Matrix,如果所有Column不是數字類型或者類型不一致,導致轉換失敗,那么apply是運算不出任何一列的結果的。

Lapply

前面說到apply是對於matrix和array的,針對list,我們可以使用lapply函數。該函數接收list,返回的結果也是一個list。其調用如下:
Apply(數據,運算函數,函數的參數)
對於Data Frame來說,如果不同的列有不同的數據類型,不能轉換成Matrix,但是卻可以轉換成List,然后使用lapply函數。
我們建立一個學生名字,年齡和成績的Data Frame,然后統計平均年齡和平均成績,由於name列不是數值類型,所以無法算平均值,所以我們可以對非數值的數據只取count數量。這里就需要用到自定義函數。
函數可以是匿名函數,也可以是之前定義好的函數,由於這里邏輯簡單,我們可以用匿名函數解決。

s<-data.frame(name=c("Devin","Edward","Lulu"),age=c(30,33,29),score=c(95,99,90))

    name age score
1  Devin  30    95
2 Edward  33    99
3   Lulu  29    90


lapply(s,function(x){if(is.numeric(x)){mean(x)}else{length(x)}})

$name
[1] 3

$age
[1] 30.66667

$score
[1] 94.66667
我們可以看到返回了一個List的結果,里面包含3個項,每個項是函數執行的結果。lapply返回的結果和傳入的List的結構相同,傳入多少個Item,返回的也是多少個Item。

Sapply

Sapply函數和Lapply函數很類似,也是對List進行處理,只是在返回結果上,Sapply會根據結果的數據類型和結構,重新構建一個合理的數據類型返回。調用格式如下:
Apply(數據,運算函數,函數的參數,simplify = TRUE, USE.NAMES = TRUE)
對於其中的simplify參數,就是指明是否對返回的結果集重新組織,如果為FALSE,那么就相當於lapply了。USE.NAMES是對字符串數據處理時,是否使用字符串作為命名的。
還是上面的例子,只是把lapply換成sapply:
sapply(s,function(x){if(is.numeric(x)){mean(x)}else{length(x)}})
    name      age    score 
 3.00000 30.66667 94.66667 
我們可以看到結果集變成了一個數字向量,而不是List了。

Mapply

這是對多個數據(multivariate)進行sapply處理,只是調用是參數位置有所變化,先把函數放前面:
mapply(運算函數,函數的參數,第一個傳入參數,第二個數據…,SIMPLIFY = TRUE,USE.NAMES = TRUE)
比如我們自定義一個函數m3,接受3個數值參數,然后將3個數字相乘返回結果:
m3<-function(a,b,c){a*b*c}
然后我們構建3個向量,他們具有相同的長度:

a<-1:5
b<-2:6
c<-5:1

現在我們要求a,b,c中的對應各位數進行m3函數的運算,也就是把a,b,c的第一個數做運算,然后把a,b,c的第二個數做運算,然后第三個數~~~這時候就用mapply很方便:

mapply(m3,a,b,c)
[1] 10 24 36 40 30

OK,就這么簡單,實現了對應的各位元素的運算。

Tapply

前面介紹的幾個apply函數都是對整體數據進行處理,而tapply是對向量中的數據進行分組處理。先看看tapply函數的調用格式:
tapply(向量數據,分組標識,運算函數,函數的參數,simplify = TRUE)
我們以一個學生數據的Data Frame為例來講解tapply函數,先構建一個新的學生數據,包含name,age,score,class,gender:

s<-data.frame(name=c("Devin","Edward","Lulu","Jeneen"),age=c(30,33,29,32),score=c(95,99,90,88),class=c(1,2,1,2),gender=c("M","M","F","F"))

    name age score class gender
1  Devin  30    95     1      M
2 Edward  33    99     2      M
3   Lulu  29    90     1      F
4 Jeneen  32    88     2      F

如果我們要計算每個班的平均成績,那么使用tapply的方法是:

tapply(s$score,s$class,mean)
   1    2 
92.5 93.5 
如果改為按gender算平均成績,那么就是:
tapply(s$score,s$gender,mean)
 F  M 
89 97 
如果同時按class和gender來看呢?這里就需要把兩個向量構建成list作為第二個參數傳入:
tapply(s$score,list(s$class,s$gender),mean)
   F  M
1 90 95
2 88 99
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM