R語言實現迴圈loop的函式解讀(帶練習)
迴圈在處理資料的時候非常重要,但不得不說寫function的時候還是得繞不少彎路,好在現在R語言有非常多函式可以直接使用,帶來不少便利。在學習寫looping function 的時候,可以先熟練掌握了以下向量化操作apply、tapply、lapply、sapply、mapply的函式,然後再自己嘗試寫自己的:
lapply | lapply(X,FUN,...) ,注意:若X不是列表,但會被強制as.list |
sapply | sapply(X, FUN,..., simplify = TRUE, USE.NAMES = TRUE) ;與Lapply相似,或者說是lapply的衍生 |
apply | apply(X, MARGIN, FUN, ...),把FUN用到array的特定margins |
tapply | tapply(X, INDEX, FUN = NULL, ..., simplify = TRUE),專門用來處理分組資料的 |
mapply | mapply(FUN, ..., MoreArgs = NULL, SIMPLIFY = TRUE,USE.NAMES = TRUE) ,mapply是sapply的變形 |
#下面使用R自帶的資料來實踐: > library(datasets) > data(iris) #在使用這個iris之前,建議大家可以先看看這個資料的具體情況 > ?iris
lapply:
lapply(list, function)
function (X, FUN, ...)
{
FUN <- match.fun(FUN)
if (!is.vector(X) || is.object(X))
X <- as.list(X)
.Internal(lapply(X, FUN))
}
<bytecode: 0x000000000263dea8>
<environment: namespace:base>
lapply的返回值是和一個和X有相同的長度的list物件,這個list物件中的每個元素是將函式FUN應用到X的每一個元素。其中X為List物件(該list的每個元素都是一個向量),其他型別的物件會被R通過函式as.list()自動轉換為list型別。
lappy()的處理物件是向量、列表或其它物件,它將向量中的每個元素作為引數,輸入到處理函式中,最後生成結果的格式為列表。在R中資料框是一種特殊的列表,所以資料框的列也將作為函式的處理物件。
試一下lapply來求'Sepal.Length'的平均值(mean)
lapply(iris, mean)
返回的是
$Sepal.Length
[1] 5.843333
$Sepal.Width
[1] 3.057333
$Petal.Length
[1] 3.758
$Petal.Width
[1] 1.199333
$Species
[1] NA
sapply
> sapply
function (X, FUN, ..., simplify = TRUE, USE.NAMES = TRUE)
{
FUN <- match.fun(FUN)
answer <- lapply(X = X, FUN = FUN, ...)
if (USE.NAMES && is.character(X) && is.null(names(answer)))
names(answer) <- X
if (!identical(simplify, FALSE) && length(answer))
simplify2array(answer, higher = (simplify == "array"))
else answer
}
<bytecode: 0x0000000015568688>
<environment: namespace:base>
sapply和lapply返回值是一樣的。但引數simplify=T,其返回值就不是list,而是matrix;相反,simplify=F,其返回值還是list。
仍用求iris每個量的mean來看一下區別:
> sapply(iris,mean)
Sepal.Length Sepal.Width
5.843333 3.057333
Petal.Length Petal.Width
3.758000 1.199333
Species
NA
> sapply(iris,mean,simplify = F)
$Sepal.Length
[1] 5.843333
$Sepal.Width
[1] 3.057333
$Petal.Length
[1] 3.758
$Petal.Width
[1] 1.199333
$Species
[1] NA
apply
> apply
function (X, MARGIN, FUN, ...)
其中X是array;MARGIN是向量(表示要將函式FUN應用到X的行還是列),若為1表示取行,為2表示取列,為c(1,2)表示行、列都計算。apply()函式的處理物件是矩陣或陣列,它逐行或逐列的處理資料,其輸出的結果將是一個向量或是矩陣。下面的例子即對一個隨機矩陣求每一行的均值。要注意的是apply與其它函式不同,它並不能明顯改善計算效率,因為它本身內建為迴圈運算。
為了方便理解 ,舉個函式的例子:
rowSums = apply(x, 1, sum)
rowMeans = apply(x, 1, mean)
colSums = apply(x, 2, sum)
colMeans = apply(x, 2, mean)
或者大家可以直接使用iris3來嘗試一下不同的結果:
tapply
> tapply
function (X, INDEX, FUN = NULL, ..., default = NA, simplify = TRUE)
用於分組統計(index)
其中X通常是一向量;INDEX是一個list物件,且該list中的每一個元素都是與X有同樣長度的因子;FUN是需要計算的函式;simplify是邏輯變數,若取值為TRUE(預設值),且函式FUN的計算結果總是為一個標量值,那麼函式tapply返回一個數組;若取值為FALSE,則函式tapply的返回值為一個list物件。需要注意的是,當第二個引數INDEX不是因子時,函式 tapply() 同樣有效,因為必要時 R 會用 as.factor()把引數強制轉換成因子。
tapply()的功能則又有不同,它是專門用來處理分組資料的,其引數要比sapply多一個。我們以iris資料集為例,可觀察到Species列中存放了三種花的名稱,我們的目的是要計算三種花瓣萼片寬度的均值。其輸出結果是陣列格式。
> tapply(1:17, fac, sum)
1 2 3 4 5
51 57 45 NA NA
> tapply(1:17, fac, sum, simplify = FALSE)
$`1`
[1] 51
$`2`
[1] 57
$`3`
[1] 45
$`4`
NULL
$`5`
NULL
> tapply(1:17, fac, range)
$`1`
[1] 1 16
$`2`
[1] 2 17
$`3`
[1] 3 15
$`4`
NULL
$`5`
NULL