本節(jié)提要:
apply()
函數(shù)sapply()
函數(shù)lapply()
函數(shù)tapply()
函數(shù)
熟悉R編程的人都知道R語言的apply
家族,而R語言入門容易,簡單學一學就能寫出一些代碼伦意,而良好的編程習慣和優(yōu)雅的代碼風格卻是一個長期潛移默化火窒、逐步積累的過程硼补。
R語言的apply
家族正是為你高效編程提供了可能性,其令人驚訝的處理方式可能會成為你選擇它們的理由熏矿。
apply()
要點:
- 作用對象:數(shù)據(jù)框(dataframe)或 矩陣(matrix)已骇;
- 輸出:一個向量离钝;
- 關鍵參數(shù):
MARGIN
與FUN
。
apply()
函數(shù)能夠快速幫助你對數(shù)據(jù)框或矩陣按行(MARGIN = 1
)或列(MARGIN = 2
)的方式來進行處理褪储,而這個處理正是由FUN
所定義的卵渴。
示例:
#a matrix
mtx <- matrix(1:9, byrow = T, nrow = 3)
mtx
# [,1] [,2] [,3]
#[1,] 1 2 3
#[2,] 4 5 6
#[3,] 7 8 9
apply(X = mtx,
MARGIN = 1, #by row
FUN = mean) #cal mean value (mean function)
#[1] 2 5 8
這段代碼實現(xiàn)了對該矩陣按行取均值的操作,最后返回一個向量鲤竹,分別對應每一行的均值浪读,當然你也可以自定義函數(shù),例如還是上面的目的辛藻,用自己寫的函數(shù)來實現(xiàn)(當然這完全沒必要):
apply(X = mtx,
MARGIN = 1, #by row
FUN = function(x){
sum(x)/length(x)
}) #cal mean value (custome function)
想給大家分享的是碘橘,這段代碼里面的x
到底是個什么?答案是 向量吱肌。也就是說 apply()
函數(shù)講數(shù)據(jù)框或矩陣給你拆成了一個個向量供你進行操作痘拆,我們來簡單驗證一下:
apply(X = mtx,
MARGIN = 1, #by row
FUN = function(x){
is.vector(x)
})
#[1] TRUE TRUE TRUE
sapply()
要點:
- 作用對象:數(shù)據(jù)框(dataframe),向量(vector)或 列表(list)氮墨;
- 輸出:向量(vector)或 矩陣(matrix)纺蛆;
- 關鍵參數(shù):
FUN
。
從本質上看规揪,R語言的數(shù)據(jù)框是一種特殊的列表(每個組件長度都相等的列表)桥氏。這個組件就是數(shù)據(jù)框的每一列,由于數(shù)據(jù)框的特點猛铅,這些組件的類型是不一樣的识颊,有的是字符型向量,有的是數(shù)值型向量等等奕坟。
首先來看sapply()
函數(shù)是如何處理列表的:
#a list
list <- list(a = sample(1:10, 5),
b = 1:5)
list
#$a
#[1] 4 6 8 1 5
#$b
#[1] 1 2 3 4 5
sapply(list, FUN = sum)
# a b
#24 15
最終是對列表的每個組件進行了函數(shù)(sum()
)的操作祥款,返回了一個向量。
基于前面對數(shù)據(jù)框和列表之間聯(lián)系的認識月杉,我們很自然的就可以知道刃跛,如果將sapply()
函數(shù)作用到數(shù)據(jù)框上會發(fā)生什么:對數(shù)據(jù)框的每一列進行相應的操作:
#a dataframe
dataframe <- data.frame(a = sample(1:10, 5),
b = 1:5)
dataframe
# a b
#1 2 1
#2 9 2
#3 10 3
#4 5 4
#5 6 5
sapply(dataframe, FUN = sum)
# a b
#32 15
果然是對數(shù)據(jù)框的每一列進行了求和。
lapply()
要點:
- 作用對象:數(shù)據(jù)框(dataframe)苛萎,向量(vector)或 列表(list)桨昙;
- 輸出:列表(list);
- 關鍵參數(shù):
FUN
腌歉。
lapply()
和sapply()
函數(shù)很像蛙酪,不同點在于前者的輸出是列表,這在很多時候會給我們帶來一些意想不到的便利翘盖。暫時只做一個簡單的使用示例:
list <- list(a = sample(1:10, 5),
b = 1:5)
list
lapply(list, FUN = sum)
#$a
#[1] 38
#$b
#[1] 15
tapply()
要點:
- 作用對象:向量(vector)桂塞;
- 輸出:向量(vector);
- 關鍵參數(shù):
INDEX
馍驯,FUN
阁危。
tapply()
函數(shù)在進行分組統(tǒng)計時具有非常大的作用玛痊,簡單理解來說,tapply()
函數(shù)就是對向量X按照因子INDEX
進行函數(shù)FUN
的操作狂打。這里我們以鳶尾花內置數(shù)據(jù)集為例來看看:
head(iris)
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#1 5.1 3.5 1.4 0.2 setosa
#2 4.9 3.0 1.4 0.2 setosa
#3 4.7 3.2 1.3 0.2 setosa
#4 4.6 3.1 1.5 0.2 setosa
#5 5.0 3.6 1.4 0.2 setosa
#6 5.4 3.9 1.7 0.4 setosa
#calculate mean Sepal length for each species
tapply(iris$Sepal.Length,
INDEX = factor(iris$Species), #group by species
FUN = mean) #calculate mean value
# setosa versicolor virginica
# 5.006 5.936 6.588
這實際上和dplyr
的group_by()
很像擂煞,也就是說這個功能還可以用這段代碼實現(xiàn):
library(dplyr)
iris %>%
group_by(Species) %>%
summarise(mean = mean(Sepal.Length))
不過返回的是數(shù)據(jù)框罷了。