for函数 R语言 r语言中的for函数_for函数 R语言


前言

Apply系列函数作为R语言中用于替换for和while循环的利器,在批量循环计算的过程中发挥着非常重要的作用,其他的R包如dplyr,plyr和data.table的很多数据操作思路和apply系列函数有很多的借鉴和相似之处,最经典的就是dplyr中的group_by+summarize可以完美的替代tapply函数。

当然在现阶段,国外推特有一个很火的选择题,就是“你在使用R语言的时候,是使用tidyverse还是base R”。人们都说tidyverse完全是开发了一套独立于R语言的另一套语法,几乎是在完全不使用base R的情况下完成Data science的所有流程。但是,对于一个真正的R爱好者来说,tidyverse固然好用,但是R基础语法必须还是要掌握,对于自己后期编写自己的R包或者集成函数都是极好的。

apply

Apply Functions Over Array Margins
Description:
Returns a vector or array or list of values obtained by applying a
function to margins of an array or matrix.
Usage:
apply(X, MARGIN, FUN, ...)
Arguments:
X: an array, including a matrix.
MARGIN: a vector giving the subscripts which the function will be
applied over. E.g., for a matrix ‘1’ indicates rows, ‘2’
indicates columns, ‘c(1, 2)’ indicates rows and columns.
Where ‘X’ has named dimnames, it can be a character vector
selecting dimension names.
FUN: the function to be applied: see ‘Details’. In the case of
functions like ‘+’, ‘%*%’, etc., the function name must be
backquoted or quoted.
...: optional arguments to ‘FUN’.

apply函数重要的参数有3个,传入的数据X,操作的行列Margin,运行的函数FUN。

传入的数据X:array或matrix,但是基于实际情况,传入的数据大部分都是矩阵

Margin:1代表处理行,2代表处理列

FUN:处理的函数,可以是自带函数或者匿名函数


a<-matrix(runif(100)*10,nrow=20)
apply(a, 1, mean)
apply(a, 1 , function(x){x[1]+x[2]})
apply(a, 1, mean, na.rm=TRUE)


sapply & lapply

apply的短板在于无法处理数据框或者list数据结构,常规情况下的数据都是由外部数据导入或者SQL数据库当中提取,所以对于dataframe的数据是很常见的。sapply和lapply其实就和表兄弟相似,两者工作的方法是一样的,只是根据参数的不同导致返回值的数据类型不同,sapply返回为vector,而lapply返回为list

Description:
‘lapply’ returns a list of the same length as ‘X’, each element of
which is the result of applying ‘FUN’ to the corresponding element
of ‘X’.
‘sapply’ is a user-friendly version and wrapper of ‘lapply’ by
default returning a vector, matrix or, if ‘simplify = "array"’, an
array if appropriate, by applying ‘simplify2array()’. ‘sapply(x,
f, simplify = FALSE, USE.NAMES = FALSE)’ is the same as ‘lapply(x,
f)’.


sapply(subset(iris, select=-Species), mean)
Sepal.Length  Sepal.Width Petal.Length  Petal.Width
    5.843333     3.057333     3.758000     1.199333
----------------------------------
lapply(subset(iris, select=-Species), mean)
$Sepal.Length
[1] 5.843333

$Sepal.Width
[1] 3.057333

$Petal.Length
[1] 3.758

$Petal.Width
[1] 1.199333


之于大家在使用的时候是sapply还是lapply,根据大家的实际情况和后续数据分析的需要来进行选择,但是无论选择哪一个,都比for循环快还节省内存。

tapply & sapply+split

tapply也同样是对数据进行批量操作,但是是根据分组情况进行的计算(也就是factor)

Description:
Apply a function to each cell of a ragged array, that is to each
(non-empty) group of values given by a unique combination of the
levels of certain factors.
Usage:
tapply(X, INDEX, FUN = NULL, ..., default = NA, simplify = TRUE)

INDEX便是分组变量名称,X是需要处理的数据列


tapply(iris$Petal.Length, iris$Species, sum)
    setosa versicolor  virginica
      73.1      213.0      277.6


sapply+split是完全可以代替tapply。split就是将数据按照因子分组并返回为list,然后sapply处理。


sapply(split(iris$Petal.Length,iris$Species), mean)
    setosa versicolor  virginica
     1.462      4.260      5.552


得到的结果和使用tapply是完全一样的

结语

apply家族函数还包含mapply和vapply等,基于大家使用R的经验可以自行查看文档去使用,上面介绍的便是常用的apply函数,可以极大程度的节省时间和减少for循环运行所消耗的时间和内存。

functional > purrr or apply series > for & while

上诉便是我本人在使用R语言处理更重数据时得出的结论,和大家分享