R語言中的apply函數族

2021-02-19 生物信息學

前言

apply函數族是R語言中數據處理的一組核心函數,通過使用apply函數,我們可以實現對數據的循環、分組、過濾、類型控制等操作。但是,由於在R語言中apply函數與其他語言循環體的處理思路是完全不一樣的,所以apply函數族一直是初學者玩不轉的一類核心函數。很多R語言新手,寫了很多的for循環代碼,也不願意多花點時間把apply函數的使用方法了解清楚,最後把R代碼寫的跟C似得。

簡介

由於R語言的apply家族函數是用C寫的,所以使用apply進行遍歷的執行效率遠遠高於自己編寫的循環語句。為了面向不同的數據類型,不同的返回值,apply函數組成了一個函數族,包括了8個功能類似的函數,具體如下表所示。下面我們一個一個來介紹。

apply函數

apply函數是最常用的代替for循環的函數。apply函數可以對矩陣、數據框、數組(二維、多維),按行或列進行循環計算,對子元素進行迭代,並把子元素以參數傳遞的形式給自定義的FUN函數中,並返回計算結果。調用格式如下:

apply(X, MARGIN, FUN, ...)

X: 是一個數組(array),也就是說輸入必須都是相同類型的數據,要麼都是數值型,要麼都是字符型。如果是一個混合數據類型的data.frame,那麼就會嘗試用as.matrix強制轉換數據。

MARGIN:表示對行(1)或者是對列(2)應用函數。

FUN: 可是R自帶函數,如mean,sum等。也可以是自己編寫的函數。

... :FUN中的額外參數。

現在假設我們需要對一個矩陣的每一行求和,那麼用apply怎麼實現呢?

x<-matrix(1:12, ncol=3)apply(x, 1, sum)[1] 15 18 21 24

一行代碼搞定!當然你說可以使用 rowSums(x)也一樣能得到結果,但是如果稍微複雜點,rowSums函數就不行了。比如說讓數據框的x1列加1,並計算出x1,x2列的均值,這個時候就需要利用apply調用自定義函數了,可以說這才是apply強大的真正原因。

第一步,生成matrix

x <- cbind(x1 = 10, x2 = c(1:4, 2:5)); x     x1 x2[1,] 10  1[2,] 10  2[3,] 10  3[4,] 10  4[5,] 10  2[6,] 10  3[7,] 10  4[8,] 10  5

第二步,自定義函數myFUN,第一個參數x為數據, 第二、三個參數為自定義參數,可以通過apply的'...'進行傳入。

myFUN <- function(x, c1, c2) {  c(sum(x[c1], 1), mean(x[c2])) }

第三步,通過apply調用上面自定義的函數

apply(x, 1, myFUN, c1='x1', c2=c('x1', 'x2'))     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8][1,] 11.0   11 11.0   11   11 11.0   11 11.0[2,]  5.5    6  6.5    7    6  6.5    7  7.5

是不是很簡單,通過for循環的方式,也可以很容易的實現上面計算過程,但是需要一些額外的操作,比如構建循環體、定義結果數據集、合併每次循環的結果到結果數據集。

lapply函數

lapply函數是一個最基礎循環操作函數之一,用來對list、data.frame數據集進行循環,並返回和X長度同樣的list結構作為結果集,通過lapply的開頭的第一個字母』l』就可以判斷返回結果集的類型。

下面以計算list中的每個元素對應數據的分位數為例,展示該函數的特性。

x <- list(a = 5:20, b = rnorm(6,10,5), c = c(FALSE,FALSE,TRUE,TRUE,TRUE,TRUE))lapply(x, fivenum)$`a`[1]  5.0  8.5 12.5 16.5 20.0
$b[1] 3.772836 11.750169 14.611470 17.395703 23.898115
$c[1] 0 0 1 1 1

可以看到,lapply很方便地把list數據集進行循環操作了,此外,它還可以對data.frame數據集按列進行循環,但如果傳入的數據集是一個向量或矩陣對象,那麼直接使用lapply就不能達到想要的效果了,lapply會分別循環矩陣中的每個值,而不是按行或按列進行分組計算。

x <- cbind(x=3, y=c(2:1, 4:5))lapply(data.frame(x), sum)$x[1] 12
$y[1] 12

sapply函數

sapply函數是一個簡化版的lapply,sapply增加了2個參數simplify和USE.NAMES,主要就是讓輸出看起來更友好,返回值為向量,而不是list對象。

vapply函數

vapply類似於sapply,提供了FUN.VALUE參數,用來控制返回值的行名,這樣可以讓程序更健壯。

mapply函數

mapply是sapply的變形函數,類似多變量的sapply,但是參數定義有些變化。第一參數為自定義的FUN函數,第二個參數』…』可以接收多個數據,作為FUN函數的參數調用。比如,比較3個向量大小,按索引順序取較大的值。

# 定義3個向量x <- 4:10y <- 10:4z <- round(runif(7, -5, 5))
# 按索引順序取較大的值。mapply(max, x, y, z)[1] 10 9 8 7 8 9 10

又比如想生成4個符合正態分布的數據集,分別對應的均值和方差為c(1,10,100,1000)。

# m為均值,v為方差m <- v <- c(1, 10, 100, 1000)
# 生成4組數據,按列分組mapply(rnorm, rep(4,4), m, v)[,1] [,2] [,3] [,4][1,] 1.1321892 11.119809 -12.65840 525.4851[2,] 3.3765492 8.032937 -44.84486 700.5648[3,] 0.1849429 6.717259 157.55199 1430.6167[4,] 1.8121539 15.392016 32.86186 1621.0613

tapply函數

tapply用於分組的循環計算,通過INDEX參數可以把數據集X進行分組,相當於group by的操作。例如,計算不同品種的鳶尾花的花瓣(iris)長度的均值。

# 通過iris$Species品種進行分組tapply(iris$Petal.Length, iris$Species, mean)    setosa versicolor  virginica      1.462      4.260      5.552

rapply函數

rapply是一個遞歸版本的lapply,它只處理list類型數據,對list的每個元素進行遞歸遍歷,如果list包括子元素則繼續遍歷。例如,對一個list的數據進行過濾,把所有數字型的數據進行從小到大的排序。

x <- list(a=12, b=1:4, c=c('b', 'a'))y <- data.frame(a=rnorm(10), b=1:10)lst <- list(x=x, y=y)rapply(lst, sort, classes='numeric', how='replace')$`x`$`x`$`a`[1] 12
$`x`$b[1] 1 2 3 4
$`x`$c[1] "b" "a"

$ya b1 -2.28818912 12 -1.11604471 23 -0.71061407 34 -0.47929464 45 -0.45064871 56 -0.32539516 67 -0.09147763 78 0.32032781 89 1.67678507 910 1.71896910 10

eapply函數

對一個環境空間中的所有變量進行遍歷。eapply函數平時很難被用到,但對於R包開發來說,環境空間的使用是必須要掌握的。特別是當R要做為工業化的工具時,對變量的精確控制和管理是非常必要的。

總結

從上面這8個函數的參數定義,我們可以發現它們都接收一個函數作為它的參數,在編程的世界裡,這種把函數作為參數傳入的函數稱為高階函數,函數式編程就是指這種高度抽象的編程範式。這種編程範式與面向對象的範式的差異如下圖

相關焦點

  • 乾貨 掌握R語言中的apply函數族
    原因在於R的循環操作for和while,都是基於R語言本身來實現的,而向量操作是基於底層的C語言函數實現的,從性能上來看,就會有比較明顯的差距了。那麼如何使用C的函數來實現向量計算呢,就是要用到apply的家族函數,包括apply, sapply, tapply, mapply, lapply, rapply, vapply, eapply等。
  • R語言向量化運算:apply函數族用法心得
    R語言和Python的忠實擁躉,為成為一名未來的數據科學家而奮鬥終生。個人公眾號:數據科學家養成記 (微信ID:louwill12)當初入坑R語言的時候,就在各種場合看到老司機的忠告,「儘量避免使用循環!」一開始並不明白這其中的奧義,直到後來對R語言有深入接觸後,才領會R語言在向量化運算方面的強大功能。本篇內容就總結小編在使用R語言向量化運算apply函數族的一些心得體會。
  • 【R知識】R語言apply函數族筆記
    現在我的看法傾向於,R不是一種通用型的程式語言,而是一種統計領域的軟體工具。因此,不能用通用型編程的思維來設計R代碼。在    Andrew Lim 關於R和Python的對比回答中,R是一種面向數組(array-oriented)的語法,它更像數學,方便科學家將數學公式轉化為R代碼。而Python是一種通用程式語言,更工程化。在使用R時,要儘量用array的方式思考,避免for循環。
  • R 語言 apply 族函數基本用法(一)
    R 語言有很多強大的循環函數,與其他程式語言(比如 Java、C/C++、Python、Julia 等)手寫循環不同,R 使用內置的循環函數會讓你的代碼更具有可讀性
  • 【R函數學習】R語言 apply函數家族詳解
    lapplyApply a Function over a List or Vector對列表或者向量使用函數lapply(X, FUN, ...)eapplyApply a Function Over Values in an Environment對環境中的值使用函數eapply(env, FUN, ..., all.names = FALSE, USE.NAMES = TRUE)mapplyApply a Function to Multiple List or
  • R語言中plyr包
    文章轉載自哈爾濱商業大學銀河統計工作室前言  apply族函數是R語言中很有特色的一類函數,包括了apply、sapply、lapply、tapply
  • R語言 apply函數家族詳解
    來自Conda的新浪博客apply {base}通過對數組或者矩陣的一個維度使用函數生成值得列表或者數組
  • R語言apply家族函數的用法及其比較
    在平常的編程過程中我們應該儘量避免使用循環,而採用向量化的編程語法可以幫助我們有效提高數據處理效率。本文我們主要介紹如何使用R語言中的apply家族函數來實現向量化運算。案例中需要用到的數據集為了更好的理解apply家族函數的用法,本文需要用到mtcars數據集和beavers數據集。
  • 使用apply族函數進行向量化運算替代for循環
    R基礎包base的apply族函數採用向量化運算實現批量計算,相較於for循環語句其代碼更加簡潔、運行速度也更快,恰當地運用這些函數能夠極大提高代碼質量。本篇主要介紹apply族函數的apply(),lapply(),sapply(),mapply()和tapply()函數。
  • 如何高效運行R語言
    R語言的很多基礎函數也是用C語言寫的,你可以認為R函數是對C語言函數的包裝,方便用戶的調用。如何在R中編寫並調用C函數呢?請參考:在R語言中寫一個C函數提高R運行效率的另一個策略是儘可能少的調用函數。apply族函數常見的apply族函數有如下一些:個人使用習慣不同,本人最常使用的是apply和lapply。apply族函數具體用法不在此處做詳細介紹。
  • 【R函數學習】R語言時間序列函數整理
    #arma模型library(fUnitRoots) #進行單位根檢驗library(FinTS) #調用其中的自回歸檢驗函數library(fGarch) #GARCH模型library(nlme) #調用其中的gls函數library(fArma) #進行擬合和檢驗【基本函數
  • R中強大的apply、tapply、lapply、sapply、mapply家族
    批量處理函數有很重要的apply族函數:lapply sapply apply tapply mapply。
  • apply家族
    ()函數是一個很R語言的函數,可以起到很好的替代冗餘的for循環的作用,R語言的循環操作for和while,都是基於R語言本身來實現的,而向量操作是基於底層的C語言函數實現的,所以使用apply()家族進行向量計算是高性價比的。
  • Pandas高級應用(map()與apply()函數)
    一.map()函數import pandas
  • Day7:R語言課程 (R語言進行數據可視化)
    使用R base包提供的函數'mean()':mean(rpkm_ordered[,"sample1"])只想要其中一個樣本(數據框中的1列)的平均值,可以這樣實現,但要從所有12個樣本中獲取此信息該如何實現?程式語言通常有辦法允許多次執行代碼,或者在「循環」中執行。
  • 成為R語言高手:再談apply和for loop循環
    用過一段時間R的朋友估計對R語言的for loop循環和apply函數孰優孰劣問題都不會陌生,網絡上可以找到很多討論,知乎上類似的問題也不少,可以看到大多數的意見是不要用
  • R語言——使用apply function替代for loop循環語句
    不過在進行結果重現的過程中,我用R始終沒辦法得到和作者一致的結果,而作者又是用的Stata,所以我目前還在找是哪裡出現了問題。如果之後問題解決了,我會再把這篇論文推出來的。有興趣的朋友,可以點擊文末閱讀原文查看這篇論文。既然難的做不了,今天就先講個簡單的,R語言裡面for loop的替代者apply function。
  • R語言時間序列函數大全(收藏!)
    library(fGarch) #GARCH模型library(nlme) #調用其中的gls函數library(fArma) #進行擬合和檢驗數學函數abs,sqrt:絕對值,平方根 log, log10, log2 , exp:對數與指數函數 sin,cos,tan,asin,acos,atan
  • R數據分析:apply()的各種變體你分清了嗎?
    apply函數可以看作是循環的替代方法,在R語言中,apply函數的變體有很多,好多時候同學搞不清到底該用apply呢,還是tapply呢還是sapply
  • R點石成金三人組:apply,lapply,sapply
    首先,我們來看三人組的大哥:apply函數。apply函數是這三個函數的精髓,lapply是它的變種,sapply是lapply的精華簡潔版本。apply函數的基本命令格式是:apply(數據,向量,函數)。這個「數據、向量、函數」是什麼意思呢?