84.关于apply族的lapply/sapply/vapply

【上一篇:83.关于purrr包中的函数与apply函数的运行原理说明-十分详细】
【下一篇:85.关于tapply函数】

    之所以上篇将apply写那么细,是因为我一直有无法理解和记忆apply()返回结果的困扰。好好研究一遍之后发现只要记住以下几个点其实就理解了。
    1)apply()的输入是array或matrix,也可以是任何有dim信息的对象[也许不太对,大致是这样],输出是向量、数组或列表[想得到数据框?用类似as.data.frame)()函数转吧]。
    2)apply()的输出格式由调用函数返回向量的长度和simplify参数共同确定。
    3)apply()是for循环的紧凑版,理解其最终输出可以分两个阶段:第一阶段,每次调用函数的返回结果存储在list中,第二阶段,循环结束后再决定要不要尽可能简化输出,atomic vector的结构比list简单,所以list可以简化成atomic vector。
    下面开始apply族的其他函数解读。

lapply函数

    Apply a Function over a List or Vector。(这里的vector我很费解,难道是因为List也是vector?)
    lapply()函数是参数最少,返回结果也很固定的一个函数。

lapply(X, FUN, ...)
输入参数

    X:输入对象,一个List(必须),如果是其他对象,会用as.list()强制转换成list。例如如果是data.frame,就会先as.list(dataframe)。
    FUN:调用的函数
    ...:传递到FUN的可选参数

输出结果

    lapply()的输出也是列表,长度与输入X的长度一致

# 创建一个list
> (x <- list(a = 1:10, beta = exp(-3:3), logic = c(TRUE,FALSE,FALSE,TRUE)))
$a
 [1]  1  2  3  4  5  6  7  8  9 10

$beta
[1]  0.04978707  0.13533528  0.36787944  1.00000000  2.71828183
[6]  7.38905610 20.08553692

$logic
[1]  TRUE FALSE FALSE  TRUE
# 求列表中的每个元素求均值
> lapply(x, mean)
$a
[1] 5.5

$beta
[1] 4.535125

$logic
[1] 0.5
# 创建一个数据框
> (n<-data.frame(a=1:5,b=6:10))
  a  b
1 1  6
2 2  7
3 3  8
4 4  9
5 5 10
# 如果输入对象是数据框,则会先被as.list()强制转成list
> as.list(n)
$a
[1] 1 2 3 4 5

$b
[1]  6  7  8  9 10


sapply函数

    sapply()函数是lapply()函数的用户优好版,输入参数一致,但输出更多样化,可以根据自己的需要设置。

sapply(X, FUN, ..., simplify = TRUE, USE.NAMES = TRUE)
输入参数

    simplify:逻辑值或字符串,表示是否结果应该尽可能地被简化为向量、矩阵或更高维度的数组。默认为TRUE,表示合适的情况下简化为向量或矩阵;如果simpliy="array",表示结果可能是数组;当然不简化的时候输出和lapply()也一样是list啦
    sapply()函数中的简化是只有在每次调用FUN后的结果长度相同时发生的。每次调用FUN后返回的结果长度为1,则最终结果简化为向量;大于1,则最终结果简化为矩阵,矩阵的列数等于X的元素个数。
    simplify="array"的时候,简化的发生是通过调用simplify2array()函数实现的。
    如果进行了简化,则输出类型在将成对列表强制转换为列表之后,由层次结构中返回值的最高类型NULL < raw < logical < integer < double < complex < character < list < expression确定。

    USE.NAMES:逻辑值,默认为TRUE,表示如果X是character且结果也没有names的话,就将X作为结果的names。[好吧,我测试了几种情况也不知道这个参数实在怎么应用的。总之,如果输入有names,那结果的名字就由输入的names确定了。]前面一直在举数字计算的例子,这里举一个输入是character类型的例子吧,也换换心情。

> v <- list(A=letters[1:4],B=letters[5:8])
# 默认简化
> sapply(v, paste, "-lucky")
     A          B         
[1,] "a -lucky" "e -lucky"
[2,] "b -lucky" "f -lucky"
[3,] "c -lucky" "g -lucky"
[4,] "d -lucky" "h -lucky"
# 不简化
> sapply(v, paste, "-lucky", simplify = F)
$A
[1] "a -lucky" "b -lucky" "c -lucky" "d -lucky"

$B
[1] "e -lucky" "f -lucky" "g -lucky" "h -lucky"

    sapply(x, f, simplify = FALSE, USE.NAMES = FALSE)与lapply(x,f)等价。

vapply函数

    vapply()函数与sapply()函数相似,但是有一个预先指定的返回值类型,所以它可以更安全(有时更快)使用。

vapply(X, FUN, FUN.VALUE, ..., USE.NAMES = TRUE)

    FUN.VALUE:一个自己生成的向量,给定FUN返回值的模板,可以给返回值加上name,这样简化成matrix的时候就有行名了。
    vapply()返回一个与FUN.VALUE类型匹配的vector或数组。如果length(FUN.VALUE) == 1,则返回与X长度相同的向量,否则返回一个数组。如果FUN.VALUE不是一个数组,结果是一个length(FUN.VALUE)行和length(X)列的矩阵,否则是一个 dim(a) == c(dim(FUN.VALUE), length(X))的数组。

# 这个例子来自lapply函数的说明文档
# 返回的i39是一个list
> i39 <- sapply(3:9, seq)
#  求i39中每个元素的fivenum,因为FUN返回向量长度相等,所以默认简化为matrix
> sapply(i39, fivenum)
     [,1] [,2] [,3] [,4] [,5] [,6] [,7]
[1,]  1.0  1.0    1  1.0  1.0  1.0    1
[2,]  1.5  1.5    2  2.0  2.5  2.5    3
[3,]  2.0  2.5    3  3.5  4.0  4.5    5
[4,]  2.5  3.5    4  5.0  5.5  6.5    7
[5,]  3.0  4.0    5  6.0  7.0  8.0    9
# 每次调用fivenum函数,返回的向量没有name,这里通过设定FUN.VALUE指定了格式,带名字的向量。
> vapply(i39, fivenum,
+        c(Min. = 0, "1st Qu." = 0, Median = 0, "3rd Qu." = 0, Max. = 0))
        [,1] [,2] [,3] [,4] [,5] [,6] [,7]
Min.     1.0  1.0    1  1.0  1.0  1.0    1
1st Qu.  1.5  1.5    2  2.0  2.5  2.5    3
Median   2.0  2.5    3  3.5  4.0  4.5    5
3rd Qu.  2.5  3.5    4  5.0  5.5  6.5    7
Max.     3.0  4.0    5  6.0  7.0  8.0    9

    本篇实在写不下了,下篇再写tapply()
【上一篇:83.关于purrr包中的函数与apply函数的运行原理说明-十分详细】
【下一篇:85.关于tapply函数】

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容