R语言实现循环loop的函数解读(带练习)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/kidpea_lau/article/details/82756446

循环在处理数据的时候非常重要,但不得不说写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


更多的练习可以参照:R Programming Week 3 Quiz & Ans 

猜你喜欢

转载自blog.csdn.net/kidpea_lau/article/details/82756446
今日推荐