8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

分组函数(tapply、by、aggregate)和 *apply 系列

Gereon will not feed AI 2月前

90 0

每当我想在 R 中执行 \'map\'py 操作时,我通常会尝试使用 apply 系列中的函数。但是,我从未完全理解它们之间的区别 -- 如何 {sapply、lapply 等}...

每当我想在 R 中执行某些\'map\'py 操作时,我通常会尝试使用该 apply 系列中的函数。

然而,我从来没有完全理解它们之间的区别——{ sapply , lapply 等} 如何将函数应用于输入/分组输入,输出会是什么样子,甚至输入可以是什么——所以我经常只是仔细检查它们直到得到我想要的。

有人可以解释一下何时如何使用哪一个吗?

我目前的理解(可能不正确/不完整)是......

  1. p5

  2. p6

  3. apply(matrix, 1/2, f) :输入是一个矩阵。输出是一个向量,其中元素 i 是 f(矩阵的第 i 行/第 i 列)
  4. tapply(vector, grouping, f) :输出是一个矩阵/数组,其中矩阵/数组中的元素是 f 向量分组 g ,并 g 被推送到行/列名称
  5. by(dataframe, grouping, f) :设为 g 分组。应用于 f 组/数据框的每一列。漂亮地打印分组和 f 每列的值。
  6. aggregate(matrix, grouping, f) :类似于 by ,但聚合不会漂亮地打印输出,而是将所有内容粘贴到数据框中。

附带问题:我还没有学过 plyr 或 reshape - 是否会 plyr 完全 reshape 取代这些?

帖子版权声明 1、本帖标题:分组函数(tapply、by、aggregate)和 *apply 系列
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由Gereon will not feed AI在本站《list》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 有很多很棒的答案讨论了每个函数用例的差异。没有一个答案讨论性能差异。这是合理的,因为不同的函数需要不同的输入并产生不同的输出,但它们中的大多数都有一个共同的目标,即按系列/组进行评估。我的答案将重点关注性能。由于上述原因,从向量创建的输入包含在计时中,因此函数也 apply 没有被测量。

    我一次测试了两个不同的函数 sum length 。测试的输入量为 50M,输出量为 50K。我还包含了两个目前流行的软件包,在提出问题时它们还没有被广泛使用, data.table dplyr 。如果您追求良好的性能,这两个软件包绝对值得一看。

    library(dplyr)
    library(data.table)
    set.seed(123)
    n = 5e7
    k = 5e5
    x = runif(n)
    grp = sample(k, n, TRUE)
    
    timing = list()
    
    # sapply
    timing[["sapply"]] = system.time({
        lt = split(x, grp)
        r.sapply = sapply(lt, function(x) list(sum(x), length(x)), simplify = FALSE)
    })
    
    # lapply
    timing[["lapply"]] = system.time({
        lt = split(x, grp)
        r.lapply = lapply(lt, function(x) list(sum(x), length(x)))
    })
    
    # tapply
    timing[["tapply"]] = system.time(
        r.tapply <- tapply(x, list(grp), function(x) list(sum(x), length(x)))
    )
    
    # by
    timing[["by"]] = system.time(
        r.by <- by(x, list(grp), function(x) list(sum(x), length(x)), simplify = FALSE)
    )
    
    # aggregate
    timing[["aggregate"]] = system.time(
        r.aggregate <- aggregate(x, list(grp), function(x) list(sum(x), length(x)), simplify = FALSE)
    )
    
    # dplyr
    timing[["dplyr"]] = system.time({
        df = data_frame(x, grp)
        r.dplyr = summarise(group_by(df, grp), sum(x), n())
    })
    
    # data.table
    timing[["data.table"]] = system.time({
        dt = setnames(setDT(list(x, grp)), c("x","grp"))
        r.data.table = dt[, .(sum(x), .N), grp]
    })
    
    # all output size match to group count
    sapply(list(sapply=r.sapply, lapply=r.lapply, tapply=r.tapply, by=r.by, aggregate=r.aggregate, dplyr=r.dplyr, data.table=r.data.table), 
           function(x) (if(is.data.frame(x)) nrow else length)(x)==k)
    #    sapply     lapply     tapply         by  aggregate      dplyr data.table 
    #      TRUE       TRUE       TRUE       TRUE       TRUE       TRUE       TRUE 
    

    # print timings
    as.data.table(sapply(timing, `[[`, "elapsed"), keep.rownames = TRUE
                  )[,.(fun = V1, elapsed = V2)
                    ][order(-elapsed)]
    #          fun elapsed
    #1:  aggregate 109.139
    #2:         by  25.738
    #3:      dplyr  18.978
    #4:     tapply  17.006
    #5:     lapply  11.524
    #6:     sapply  11.326
    #7: data.table   2.686
    
返回
作者最近主题: