每当我想在R中"映射"py时,我通常会try 使用apply族中的函数.

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

有人能解释一下什么时候用哪个吗?

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

  1. sapply(vec, f):输入是一个向量.输出是一个向量/矩阵,其中元素if(vec[i]),如果f有多元素输出,则给出一个矩阵

  2. lapply(vec, f):与sapply相同,但输出是一个列表?

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

附带问题:我还没有学会plyr或reshape ——plyrreshape会完全取代所有这些吗?

推荐答案

R有许多*应用功能,这些功能在帮助文件(例如?apply)中有详细描述.然而,它们已经足够多了,刚开始使用的用户可能很难决定哪一个适合他们的情况,甚至很难记住它们.他们可能有一种普遍的感觉,"我应该在这里使用一个*apply函数",但一开始就很难让他们保持一致.

尽管*apply系列的许多功能都包含在非常流行的plyr软件包中(在其他答案中指出),但基本功能仍然很有用,值得了解.

这个答案旨在为新用户提供一个类似于signpost的答案,帮助他们针对特定问题找到正确的*apply函数.注意,这是not,目的是简单地重复或替换R文档!希望这个答案能帮助你决定哪个应用函数适合你的情况,然后由你来进一步研究它.除了一个例外,性能差异将不会得到解决.

  • apply - When you want to apply a function to the rows or columns of a matrix (and higher-dimensional analogues); not generally advisable for data frames as it will coerce to a matrix first.

     # Two dimensional matrix
     M <- matrix(seq(1,16), 4, 4)
    
     # apply min to rows
     apply(M, 1, min)
     [1] 1 2 3 4
    
     # apply max to columns
     apply(M, 2, max)
     [1]  4  8 12 16
    
     # 3 dimensional array
     M <- array( seq(32), dim = c(4,4,2))
    
     # Apply sum across each M[*, , ] - i.e Sum across 2nd and 3rd dimension
     apply(M, 1, sum)
     # Result is one-dimensional
     [1] 120 128 136 144
    
     # Apply sum across each M[*, *, ] - i.e Sum across 3rd dimension
     apply(M, c(1,2), sum)
     # Result is two-dimensional
          [,1] [,2] [,3] [,4]
     [1,]   18   26   34   42
     [2,]   20   28   36   44
     [3,]   22   30   38   46
     [4,]   24   32   40   48
    

    如果想要二维矩阵的行/列平均值或和,请确保

  • lapply - When you want to apply a function to each element of a list in turn and get a list back.

    这是许多其他*apply函数的主要功能.剥

     x <- list(a = 1, b = 1:3, c = 10:100) 
     lapply(x, FUN = length) 
     $a 
     [1] 1
     $b 
     [1] 3
     $c 
     [1] 91
     lapply(x, FUN = sum) 
     $a 
     [1] 1
     $b 
     [1] 6
     $c 
     [1] 5005
    
  • sapply - When you want to apply a function to each element of a list in turn, but you want a 101 back, rather than a list.

    如果发现自己键入unlist(lapply(...)),停止并考虑

     x <- list(a = 1, b = 1:3, c = 10:100)
     # Compare with above; a named vector, not a list 
     sapply(x, FUN = length)  
     a  b  c   
     1  3 91
    
     sapply(x, FUN = sum)   
     a    b    c    
     1    6 5005 
    

    在更高级的sapply应用中,它将试图强制

     sapply(1:5,function(x) rnorm(3,x))
    

    如果我们的函数返回一个二维矩阵,sapply将执行基本相同的操作,将每个返回的矩阵视为一个长向量:

     sapply(1:5,function(x) matrix(x,2,2))
    

    除非我们指定simplify = "array",在这种情况下,它将使用单个矩阵来构建多维数组:

     sapply(1:5,function(x) matrix(x,2,2), simplify = "array")
    

    当然,这些行为中的每一个都取决于我们返回相同长度或维度的向量或矩阵的函数.

  • vapply - When you want to use 101 but perhaps need to squeeze some more speed out of your code or 100.

    对于vapply,你基本上给R一个什么样的例子

     x <- list(a = 1, b = 1:3, c = 10:100)
     #Note that since the advantage here is mainly speed, this
     # example is only for illustration. We're telling R that
     # everything returned by length() should be an integer of 
     # length 1. 
     vapply(x, FUN = length, FUN.VALUE = 0L) 
     a  b  c  
     1  3 91
    
  • mapply - For when you have several data structures (e.g. vectors, lists) and you want to apply a function to the 1st elements of each, and then the 2nd elements of each, etc., coercing the result to a vector/array as in 100.

    在函数必须接受的意义上,这是多元的

     #Sums the 1st elements, the 2nd elements, etc. 
     mapply(sum, 1:5, 1:5, 1:5) 
     [1]  3  6  9 12 15
     #To do rep(1,4), rep(2,3), etc.
     mapply(rep, 1:4, 4:1)   
     [[1]]
     [1] 1 1 1 1
    
     [[2]]
     [1] 2 2 2
    
     [[3]]
     [1] 3 3
    
     [[4]]
     [1] 4
    
  • Map - A wrapper to 100 with 101, so it is guaranteed to return a list.

     Map(sum, 1:5, 1:5, 1:5)
     [[1]]
     [1] 3
    
     [[2]]
     [1] 6
    
     [[3]]
     [1] 9
    
     [[4]]
     [1] 12
    
     [[5]]
     [1] 15
    
  • rapply - For when you want to apply a function to each element of a 101 structure, recursively.

    为了让你了解rapply是多么不寻常,我在第一次发布这个答案时就忘了!显然,我相信很多人都在使用它,但是YMMV.rapply最好用用户定义的应用函数来说明:

     # Append ! to string, otherwise increment
     myFun <- function(x){
         if(is.character(x)){
           return(paste(x,"!",sep=""))
         }
         else{
           return(x + 1)
         }
     }
    
     #A nested list structure
     l <- list(a = list(a1 = "Boo", b1 = 2, c1 = "Eeek"), 
               b = 3, c = "Yikes", 
               d = list(a2 = 1, b2 = list(a3 = "Hey", b3 = 5)))
    
    
     # Result is named vector, coerced to character          
     rapply(l, myFun)
    
     # Result is a nested list like l, with values altered
     rapply(l, myFun, how="replace")
    
  • tapply - For when you want to apply a function to 101 of a vector and the subsets are defined by some other vector, usually a factor.

    阿普尔家族的害群之马.帮助文件对

    向量:

     x <- 1:20
    

    相同的长度定义组:

     y <- factor(rep(letters[1:5], each = 4))
    

    y定义的每个子组中x的值相加:

     tapply(x, y, sum)  
      a  b  c  d  e  
     10 26 42 58 74 
    

    在定义子组的地方可以处理更复杂的示例

R相关问答推荐

在之前合并的数据.tables中分配新列后.internal.selfref无效

R通过字符串中的索引连接数据帧r

将带有范围的字符串转换为R中的数字载体

通过绘图 Select 线串几何体并为其着色

从R中的另一个包扩展S3类的正确方法是什么

如果索引重复,聚合xts核心数据

从R导出全局环境中的所有sf(numrames)对象

在R中使用数据集名称

如何在R中对深度嵌套的tibbles中的非空连续行求和?

将饼图插入条形图

在数组索引上复制矩阵时出错

如何通过ggplot2添加短轴和删除长轴?

如何用书面利率绘制geom_bar图

如何根据R中其他变量的类别汇总值?

如何移除GGPlot中超出与面相交的任何格网像元

减go R中列表的所有唯一元素对

按组和连续id计算日期差

按镜像列值自定义行顺序

R-使用stri_trans_General()将其音译为德语字母

R try Catch in the loop-跳过缺少的值并创建一个DF,显示跳过的内容