R語言apply系列函數的基本作用是對數組(array,可以是多維)或者列表(list)按照元素或元素構成的子集合進行迭代,並將當前元素或子集合作為參數調用某個指定函數。vector是一維的array,dataframe可以看作特殊的list。
作用目標 |
在每個元素上應用 |
在子集合上應用 |
array |
apply |
tapply |
list |
lapply (…) |
by |
其中 lapply(…) 為一族函數,包括簡化版: sapply,遞歸版: rapply。其中sapply又可分為可設置返回值模板vapply和多變量版mapply。另外vector比較特殊,vector是一維的array,但是卻不全是和array使用相同的函數。在按元素迭代的情況下,使用和list一樣的 lapply 函數;而在按子集合迭代的情況下, tapply 和 by 都能用,只是返回值形式不同。
1. apply函數
在array上,沿margin方向,依次調用 FUN,返回結果通常為Array類型,如果返回值的向量長度不等,則返回List對象。margin表示數組引用的第幾維下標(即array[index1, index2, …]中的第幾個index),margin = 1表示行,2表示列,c(1,2) 表示行和列。
– 舉例1:
# 二維矩陣對象
x <- cbind(x1 = 3, x2 = c(4:1, 2:5))
dimnames(x)[[1]] <- letters[1:8]
apply(x, 2, mean, trim = .2)
apply(x, 1, mean, trim = .2)
apply(x, 2, sort)
– 舉例2:
#三維數組對象,數據向量中的值被賦給數組中的值時,將遵循“主列順序”,即第一個下標變化最快,最后的下表變化最慢。
z <- array(1:24, dim = 2:4)
apply(z, 3, mean)
apply(z, 1:2, function(x) seq_len(max(x)))
apply(z, 3, function(x) seq_len(max(x)))
注: 雖然vector是一維的array,但是不能使用apply,array只能用在二維及以上的array上,因為apply要求dim(X)的值必需是正數,vector對象的dim值為NULL。
2. tapply函數
按 indices 中的值分組,把相同值對應下標的array中的元素形成一個集合,應用到 FUN 。類似於group by indices的操作。當simplify = TRUE(默認)時,如果 FUN 返回的是一個值, tapply 返回Array,空值用NULL表示;若 FUN 返回多個值, tapply 返回list,空值使用NA表示。當simplify = FALSE時,tapply 都返回list 對象。 Array或list的長度和 indices 中不同值的個數相等。
當 FUN 為 NULL 的時候,返回一個長度和array中元素個數相等的vector,指示分組的結果,vector中相等的元素所對應的下標屬於同一組。例如,返回c(1, 2, 1, 3, 2), 表示根據傳入的 indices ,第1、3個元素作為一組,第2、5個元素作為一組,第4個元素作為一組。
– 舉例1:
#tapply應用於vector
height <- c(174, 165, 180, 171, 160)
sex<-c("F","F","M","F","M")
#返回vector
tapply(height, sex, mean)
#返回list
tapply(height, sex, mean, simplify = F)
#因為函數fivenum返回多值,即使simplify = TRUE,也是返回list對象
tapply(height, sex, fivenum)
– 舉例2:
#tapply應用於matrix
m <- matrix(c(1:10), nrow=2)
ind <- matrix(c(rep(1,5),rep(2,5)), nrow=2)
tapply(height, sex)
tapply(m, ind, mean)
tapply(m, ind, fivenum)
– 舉例3:
#tapply實現crosstable功能
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))
#以年份為行、地區為列計算銷售總量
tapply(df$sale, df[,c(‘year’,’loc’)], sum)
#以年份為行,類別為列計算銷售總量
tapply(df$sale, df[,c(‘year’,’type’)], sum)
#以年份,地區和類別計算銷售總量
tapply(df$sale, df[,c(‘year’,’loc’,’type’)],sum)
3. lapply函數
在 list 上逐個元素調用 FUN 。可以用於dataframe上,因為dataframe是一種特殊形式的list。若對象不是list和表達式類型,會先強制轉換為list后再應用於FUN函數。
– 舉例1:
#lapply應用於matrix
lst <- list(a=c(1:5), b=c(6:10))
lapply(lst, mean)
– 舉例2:
# 非List會先強制轉換為List后再求均值,這時每一個元素都是一個list的對象
x <- 1:3
lapply(x, mean)
– 舉例3:
# 對dataframe使用lapply
df <- data.frame(x=c(1:3),y=c(6:8))
lapply(df, mean)
4. sapply函數
比 lapply 多了一個 simplify 參數。如果 simplify=FALSE ,則等價於lapply 。否則,在上一種情況的基礎上,將 lapply 輸出的list簡化為vector或matrix,默認的simplify=TRUE。
– 舉例1:
x<-list(a= 1:10, beta = exp(-3:3), logic = c(TRUE,FALSE,FALSE,TRUE))
#simplify = FALSE,同lapply 返回list對象
sapply(x, mean, simplify = FALSE, USE.NAMES = FALSE)
– 舉例2:
#simplify = TRUE,以向量形式返回結果
sapply(x, mean, simplify = TRUE, USE.NAMES = FALSE)
– 舉例3:
#默認的simplify=TRUE,fivenum返回多值,因此最終返回結果為matrix對象
sapply(x, fivenum)
5. vapply函數
vapply 類似於 sapply (但返回類型只包含Array) ,但是提供了第三個參數 FUN.VALUE 用以指明返回值的形式,可以看作返回值的模板。vapply會檢測FUN的所有值是否與FUN.VALUE兼容,以使他們具有相同的長度和類型,為了實現類型的兼容,類型存在被強制轉換為更高類型的可能,轉換順序:
logical < integer < double < complex
– 舉例1:
#返回值的類型和長度要和預設值一致
x<-list(a= 1:10, beta = exp(-3:3), logic =c(TRUE,FALSE,FALSE,TRUE))
vapply(x, function(x) {c(mean(x),sd(x))}, FUN.VALUE = c(0, 0), USE.NAMES = TRUE)
6. mapply函數
mapply 是多變量版的 sapply(返回類型只包含Array) ,參數(…)部分可以接收多個數據, mapply 將FUN 應用於這些數據的第一個元素組成的數組,然后是第二個元素組成的數組,以此類推,直到用於每個參數的元素,要求多個數據的長度相同,或者是整數倍關系,如果參數長度不同,長度短的參數會被循環使用。返回值是array或list(如果返回值的向量長度不等,則返回List對象),取決於 FUN 返回值是一個還是多個。
– 舉例1:
#對兩個list對象的元素依次求和
mapply(sum, list(a=1,b=2,c=3), list(a=10,b=20,d=30))
– 舉例2:
#對第一和第二個對象使用rep函數,對象二長度較短會被循環使用
#返回對象長度不同,返回list對象
mapply(rep, c(1,2,4,5), c(3,4))
#返回對象長度相同同,返回matrix對象
mapply(rep, c(1,2,4,5), c(3,4))
– 舉例3:
#函數返回多值,因此返回matrix對象
mapply(function(x,y) c(x+y, x^y), c(1:5), c(1:5))
– 舉例4:
#使用MoreArgs給出rep的參數x值
mapply(rep, times = 1:2, MoreArgs = list(x = 42))
7. rapply函數
- rapply 是遞歸版的 lappy 。基本原理是對list作遍歷,如果其中有的元素仍然是list,則繼續遍歷;對於每個非list類型的元素,如果其類型是 classes 參數指定的類型之一,則調用 FUN 。classes="ANY"表示匹配所有類型。how參數用來指定操作方式,有三種:"replace"對元素類型在 classes 中的直接用調用 FUN,不在的保留原始值。
- "list" 新建一個list,元素類型在 classes 中的,調用 FUN ;不在 classes 中的類型,使用 deflt 。會保留原始list的結構。
- "unlist" 相當於對"list"模式下的結果調用 unlist(recursive=TRUE)
– 舉例1:
X <- list(list(a = pi, b =list(c = 2)), d = "a test")
#對X中的numeric類型的元素使用sqrt函數,保留非numeric元素值不變
rapply(X, sqrt, classes = "numeric", how ="replace")
– 舉例2:
#對X中的character類型的元素使用nchar函數,保留非nchar元素值不變
rapply(X, nchar, classes = "character", how ="replace")
– 舉例3:
#對X中的character類型的元素使用nchar函數,非character元素使用默認值deflt
rapply(X, nchar, classes = "character", deflt =as.integer(NA), how = "list")
– 舉例4:
#對X中的character類型的元素使用nchar函數,非character元素使用默認值deflt,返回結果使用unlist函數
rapply(X, nchar, classes = "character", deflt =as.integer(NA), how = "unlist")
– 舉例5:
#對X中的character類型的元素使用nchar函數,沒有設置deflt參數會直接舍棄非character元素,返回結果使用unlist函數
rapply(X, nchar, classes = "character", how ="unlist")
#對於how=list的情況,沒有設置deflt參數會使用默認值NULL
rapply(X, nchar, classes = "character", how = "list")
– 舉例6:
#對X中的numeric類型的元素使用log函數,函數參數為base=2
rapply(X, log, classes = "numeric", how ="replace", base = 2)
8. eapply函數
對environment中命名值進行FUN計算后返回一個列表值,用戶可以請求所有使用過的命名對象。
– 舉例1:
env <- new.env(hash = FALSE)
env$a <- 1:10
env$beta <- exp(-3:3)
env$logic <- c(TRUE, FALSE, FALSE, TRUE)
# 列出環境中的對象
utils::ls.str(env)
# 對每個元素計算均值
eapply(env, mean)
詳細總結見下表:
函數 |
用法 |
輸入 |
輸出 |
語法 |
apply |
對陣列行或者列使用函數 |
Array |
Array/List |
apply(X, MARGIN, FUN, …) |
lapply |
對列表或者向量使用函數 |
List/expression |
List |
lapply(X, FUN, …) |
sapply |
對列表或者向量使用函數 |
List/expression |
List/Array |
sapply(X, FUN, …, simplify = TRUE, USE.NAMES = TRUE) |
vapply |
對列表或者向量使用函數 |
List/expression |
Array |
vapply(X, FUN, FUN.VALUE, …, USE.NAMES = TRUE) |
tapply |
對不規則陣列使用函數 |
Array |
Array/List |
tapply(X, INDEX, FUN = NULL, …, simplify = TRUE) |
eapply |
對環境中的值使用函數 |
Values in an Environment |
List |
eapply(env, FUN, …, all.names = FALSE, USE.NAMES = TRUE) |
mapply |
對多個列表或者向量參數使用函數 |
List/Array |
List/Array |
mapply(FUN, …, MoreArgs = NULL, SIMPLIFY = TRUE, USE.NAMES = TRUE) |
rapply |
運用函數遞歸產生列表 |
List |
List/Vector |
rapply(object, f, classes = "ANY", deflt = NULL,how = c("unlist", "replace", "list"), …)
|