每当我想在r中做一些“映射” py时,我通常会尝试在 apply 家庭。

但是,我从来没有完全了解它们之间的差异 - {sapply, lapply, ,等等。}将功能应用于输入/分组输入,输出的外观,甚至输入可能是什么 - 因此,我经常只能通过它们,直到得到想要的东西为止。

有人可以解释如何使用哪个?

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

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

  2. lapply(vec, f): : 如同 sapply, ,但是输出是列表吗?

  3. apply(matrix, 1/2, f): :输入是矩阵。输出是向量,其中元素 i 是f(矩阵的行/Col I)
  4. tapply(vector, grouping, f): :输出是矩阵/数组,其中矩阵/数组中的元素是 f 在分组 g 矢量,以及 g 被推到行/col名称
  5. by(dataframe, grouping, f): : 让 g 成为分组。申请 f 到组/数据框的每一列。漂亮打印分组和价值 f 在每列。
  6. aggregate(matrix, grouping, f): : 如同 by, ,但是,聚合不会将所有内容都插入数据框架中,而不是漂亮的打印输出。

附带问题:我仍然没有学会Plyr或Reshape-会 plyr 或者 reshape 完全替换所有这些?

有帮助吗?

解决方案

R有许多 *应用功能,这些功能在帮助文件中得到了很好的描述(例如 ?apply)。但是,有足够的时间,开始用户可能难以确定哪个适合他们的情况,甚至记住所有这些情况。他们可能有一个普遍的感觉:“我应该在这里使用 *应用功能”,但是一开始就很难保持它们。

尽管事实(在其他答案中指出), *应用家庭的许多功能都受到了极为流行的范围 plyr 包装,基本功能仍然有用且值得了解。

这个答案旨在作为一种 路标 为了使新用户帮助他们转到正确的 *适用于其特定问题的功能。注意,这是 不是 打算简单地反思或替换R文档!希望此答案可以帮助您确定哪种 *应用功能适合您的情况,然后由您进行进一步研究。除了一个例外,绩效差异将无法解决。

  • 申请 - 当您想将函数应用于矩阵的行或列(和较高维的类似物)时;通常不建议使用数据框架,因为它将首先迫使矩阵。

    # 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
    

    如果您想要2D矩阵的行/列表示或总和,请务必调查高度优化的闪电标准 colMeans, rowMeans, colSums, rowSums.

  • lapply - 当您要依次将函数应用于列表的每个元素并恢复列表时。

    这是许多其他 *应用功能的主力。剥离他们的代码,您经常会发现 lapply 下。

    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 - 当您要依次将函数应用于列表的每个元素时,但是您想要一个 向量 返回,而不是列表。

    如果您发现自己打字 unlist(lapply(...)), ,停下来考虑sapply.

    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 将它们用作矩阵的列:

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

    如果我们的函数返回2维矩阵, sapply 将基本上做同样的事情,将每个返回的矩阵视为一个长向量:

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

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

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

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

  • vapply - 当您想使用 sapply 但是,也许需要从代码中挤出更多速度。

    为了 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 - 因为当您有几个数据结构(例如向量,列表),并且要应用一个函数,然后将每个函数应用于每个元素,然后将每个元素等等等等。 sapply.

    这是多变量的,因为您的函数必须接受多个参数。

    #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
    
  • 地图 - 包装纸 mapplySIMPLIFY = FALSE, ,因此可以保证返回列表。

    Map(sum, 1:5, 1:5, 1:5)
    [[1]]
    [1] 3
    
    [[2]]
    [1] 6
    
    [[3]]
    [1] 9
    
    [[4]]
    [1] 12
    
    [[5]]
    [1] 15
    
  • 愉快 - 当您想将函数应用于一个 嵌套列表 结构,递归。

    给您一些关于多么罕见的想法 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 - 当您想将功能应用于 子集 向量和亚集的子集由其他一些矢量(通常是一个因素)定义。

    *应用家庭的黑羊。帮助文件使用短语“破烂阵列”可以有点 令人困惑, ,但实际上很简单。

    向量:

    x <- 1:20
    

    (相同长度!)定义组的因素:

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

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

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

    可以处理更复杂的示例,如果亚组由几个因素列表的唯一组合定义。 tapply 在精神上与r中常见的分裂合并函数相似(aggregate, by, ave, ddply, 等等)因此,它的黑羊身份。

其他提示

在旁注,这是各种 plyr 功能对应于基础 *apply 功能(从Plyr网页从介绍到Plyr文档 http://had.co.nz/plyr/)

Base function   Input   Output   plyr function 
---------------------------------------
aggregate        d       d       ddply + colwise 
apply            a       a/l     aaply / alply 
by               d       l       dlply 
lapply           l       l       llply  
mapply           a       a/l     maply / mlply 
replicate        r       a/l     raply / rlply 
sapply           l       a       laply 

目标之一 plyr 是为每个功能提供一致的命名约定,并在功能名称中编码输入和输出数据类型。它还提供了输出的一致性,在该输出中 dlply() 很容易传递给 ldply() 产生有用的输出,等等。

从概念上讲,学习 plyr 比理解基础更困难 *apply 职能。

plyrreshape 在我每天使用中,功能几乎替换了所有这些功能。但是,也从简介到Plyr文档:

相关功能 tapplysweep 没有相应的功能 plyr, ,并保持有用。 merge 对于将摘要与原始数据相结合非常有用。

从幻灯片21 http://www.slideshare.net/hadley/plyr-one-data-analyalytic-strategy:

apply, sapply, lapply, by, aggregate

(希望很明显 apply 对应于 @Hadley的 aaplyaggregate 对应于 @Hadley的 ddply 等等。如果您不从此图像中获得同一幻灯片的20张滑梯将澄清。)

(左侧是输入,顶部输出)

首先 乔兰的出色答案 - 可疑的一切都会更好。

那么以下助记符可能有助于记住每种助记符。虽然有些显而易见,但有些人可能不那么 - - 因为这些在Joran的讨论中可以找到理由。

mnemonics

  • lapply 是一个 列表 应用在列表或向量上的作用并返回列表。
  • sapply 是一个 简单的 lapply (函数默认为返回向量或矩阵)
  • vapply 是一个 已验证的适用 (允许预先指定返回对象类型)
  • rapply 是一个 递归 申请嵌套列表,即列表中的列表
  • tapply 是一个 标记 应用标签标识子集的地方
  • apply通用的: :将函数应用于矩阵的行或列(或更一般地,将其函数用于数组的尺寸)

建立正确的背景

如果使用 apply 家庭对您仍然有点陌生,那么您可能缺少关键的观点。

这两篇文章可以提供帮助。他们提供了必要的背景来激励 功能编程技术apply 功能家族。

LISP的用户将立即识别范式。如果您不熟悉LISP,一旦您围绕FP,您就会获得有力的观点,可用于R-和 apply 将变得更有意义。

由于我意识到(非常出色的)这个帖子的答案缺乏 byaggregate 解释。这是我的贡献。

经过

by 如文档中所述的功能可以作为“包装器” tapply. 。的力量 by 当我们要计算一个任务时,就会出现 tapply 无法处理。一个示例是此代码:

ct <- tapply(iris$Sepal.Width , iris$Species , summary )
cb <- by(iris$Sepal.Width , iris$Species , summary )

 cb
iris$Species: setosa
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  2.300   3.200   3.400   3.428   3.675   4.400 
-------------------------------------------------------------- 
iris$Species: versicolor
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  2.000   2.525   2.800   2.770   3.000   3.400 
-------------------------------------------------------------- 
iris$Species: virginica
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  2.200   2.800   3.000   2.974   3.175   3.800 


ct
$setosa
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  2.300   3.200   3.400   3.428   3.675   4.400 

$versicolor
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  2.000   2.525   2.800   2.770   3.000   3.400 

$virginica
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  2.200   2.800   3.000   2.974   3.175   3.800 

如果我们打印这两个对象, ctcb, ,我们“本质上”具有相同的结果,唯一的区别在于它们的显示方式和不同 class 属性分别 by 为了 cbarray 为了 ct.

正如我所说的, by 当我们无法使用时会出现 tapply;以下代码是一个示例:

 tapply(iris, iris$Species, summary )
Error in tapply(iris, iris$Species, summary) : 
  arguments must have same length

r说,论点必须具有相同的长度,说“我们要计算 summary 所有变量 iris 沿着因素 Species”:但是R无法做到这一点,因为它不知道如何处理。

by 功能r调度一种特定方法 data frame 上课,然后让 summary 函数即使第一个参数的长度(也是类型)也有所不同。

bywork <- by(iris, iris$Species, summary )

bywork
iris$Species: setosa
  Sepal.Length    Sepal.Width     Petal.Length    Petal.Width          Species  
 Min.   :4.300   Min.   :2.300   Min.   :1.000   Min.   :0.100   setosa    :50  
 1st Qu.:4.800   1st Qu.:3.200   1st Qu.:1.400   1st Qu.:0.200   versicolor: 0  
 Median :5.000   Median :3.400   Median :1.500   Median :0.200   virginica : 0  
 Mean   :5.006   Mean   :3.428   Mean   :1.462   Mean   :0.246                  
 3rd Qu.:5.200   3rd Qu.:3.675   3rd Qu.:1.575   3rd Qu.:0.300                  
 Max.   :5.800   Max.   :4.400   Max.   :1.900   Max.   :0.600                  
-------------------------------------------------------------- 
iris$Species: versicolor
  Sepal.Length    Sepal.Width     Petal.Length   Petal.Width          Species  
 Min.   :4.900   Min.   :2.000   Min.   :3.00   Min.   :1.000   setosa    : 0  
 1st Qu.:5.600   1st Qu.:2.525   1st Qu.:4.00   1st Qu.:1.200   versicolor:50  
 Median :5.900   Median :2.800   Median :4.35   Median :1.300   virginica : 0  
 Mean   :5.936   Mean   :2.770   Mean   :4.26   Mean   :1.326                  
 3rd Qu.:6.300   3rd Qu.:3.000   3rd Qu.:4.60   3rd Qu.:1.500                  
 Max.   :7.000   Max.   :3.400   Max.   :5.10   Max.   :1.800                  
-------------------------------------------------------------- 
iris$Species: virginica
  Sepal.Length    Sepal.Width     Petal.Length    Petal.Width          Species  
 Min.   :4.900   Min.   :2.200   Min.   :4.500   Min.   :1.400   setosa    : 0  
 1st Qu.:6.225   1st Qu.:2.800   1st Qu.:5.100   1st Qu.:1.800   versicolor: 0  
 Median :6.500   Median :3.000   Median :5.550   Median :2.000   virginica :50  
 Mean   :6.588   Mean   :2.974   Mean   :5.552   Mean   :2.026                  
 3rd Qu.:6.900   3rd Qu.:3.175   3rd Qu.:5.875   3rd Qu.:2.300                  
 Max.   :7.900   Max.   :3.800   Max.   :6.900   Max.   :2.500     

它确实有效,结果非常令人惊讶。这是类的对象 by 那是 Species (例如,每个人)计算 summary 每个变量。

请注意,如果第一个参数是 data frame, ,调度函数必须具有该类别对象的方法。例如,我们将此代码与 mean 函数我们将拥有根本没有意义的代码:

 by(iris, iris$Species, mean)
iris$Species: setosa
[1] NA
------------------------------------------- 
iris$Species: versicolor
[1] NA
------------------------------------------- 
iris$Species: virginica
[1] NA
Warning messages:
1: In mean.default(data[x, , drop = FALSE], ...) :
  argument is not numeric or logical: returning NA
2: In mean.default(data[x, , drop = FALSE], ...) :
  argument is not numeric or logical: returning NA
3: In mean.default(data[x, , drop = FALSE], ...) :
  argument is not numeric or logical: returning NA

总计的

aggregate 可以看作是另一种不同的使用方式 tapply 如果我们以这种方式使用它。

at <- tapply(iris$Sepal.Length , iris$Species , mean)
ag <- aggregate(iris$Sepal.Length , list(iris$Species), mean)

 at
    setosa versicolor  virginica 
     5.006      5.936      6.588 
 ag
     Group.1     x
1     setosa 5.006
2 versicolor 5.936
3  virginica 6.588

两个直接区别是第二个论点 aggregate 必须 成为清单 tapply 能够 (不是强制性的)是列表,输出 aggregate 是一个数据框架,而 tapply 是一个 array.

的力量 aggregate 是可以轻松地处理数据子集 subset 论点,它具有用于的方法 ts 对象和 formula 也是。

这些元素成就 aggregate 更容易使用 tapply 在某些情况下。以下是一些示例(在文档中可用):

ag <- aggregate(len ~ ., data = ToothGrowth, mean)

 ag
  supp dose   len
1   OJ  0.5 13.23
2   VC  0.5  7.98
3   OJ  1.0 22.70
4   VC  1.0 16.77
5   OJ  2.0 26.06
6   VC  2.0 26.14

我们可以通过 tapply 但是语法稍硬,输出(在某些情况下)不可读取:

att <- tapply(ToothGrowth$len, list(ToothGrowth$dose, ToothGrowth$supp), mean)

 att
       OJ    VC
0.5 13.23  7.98
1   22.70 16.77
2   26.06 26.14

有时候我们无法使用 by 或者 tapply 我们必须使用 aggregate.

 ag1 <- aggregate(cbind(Ozone, Temp) ~ Month, data = airquality, mean)

 ag1
  Month    Ozone     Temp
1     5 23.61538 66.73077
2     6 29.44444 78.22222
3     7 59.11538 83.88462
4     8 59.96154 83.96154
5     9 31.44828 76.89655

我们无法获得以前的结果 tapply 一个电话,但我们必须计算出均值 Month 对于每个元素,然后将它们组合在一起(还请注意,我们必须调用 na.rm = TRUE, ,因为 formula 方法的方法 aggregate 功能默认为 na.action = na.omit):

ta1 <- tapply(airquality$Ozone, airquality$Month, mean, na.rm = TRUE)
ta2 <- tapply(airquality$Temp, airquality$Month, mean, na.rm = TRUE)

 cbind(ta1, ta2)
       ta1      ta2
5 23.61538 65.54839
6 29.44444 79.10000
7 59.11538 83.90323
8 59.96154 83.96774
9 31.44828 76.90000

同时 by 实际上,我们无法实现这一目标,以下函数呼叫会返回错误(但很可能与所提供的函数有关, mean):

by(airquality[c("Ozone", "Temp")], airquality$Month, mean, na.rm = TRUE)

其他时间,结果是相同的,差异仅在类中(然后是如何显示/打印,而不仅 - 示例,如何将其子集)对象:

byagg <- by(airquality[c("Ozone", "Temp")], airquality$Month, summary)
aggagg <- aggregate(cbind(Ozone, Temp) ~ Month, data = airquality, summary)

以前的代码实现了相同的目标和结果,在某些时候,使用哪种工具只是个人品味和需求的问题;在子集方面,前两个对象的需求非常不同。

有很多很棒的答案,讨论了每个功能的用例中的差异。没有答案讨论性能的差异。这是合理的原因,各种功能都会期望各种输入并产生各种输出,但大多数功能都有一个普遍的共同目标,可以按串联/组进行评估。我的答案将集中在性能上。由于从向量的输入创建上方,也包括在计时中 apply 功能未测量。

我已经测试了两个不同的功能 sumlength 立刻。经过测试的体积为50m,输出时为50k。我还包括了两个目前流行的包裹,这些包在问问题时未被广泛使用, data.tabledplyr. 。如果您的目标是良好的表现,那么两者绝对值得一看。

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

也许值得一提 ave. avetapply友善的堂兄。它返回结果,您可以直接插入数据框架。

dfr <- data.frame(a=1:20, f=rep(LETTERS[1:5], each=4))
means <- tapply(dfr$a, dfr$f, mean)
##  A    B    C    D    E 
## 2.5  6.5 10.5 14.5 18.5 

## great, but putting it back in the data frame is another line:

dfr$m <- means[dfr$f]

dfr$m2 <- ave(dfr$a, dfr$f, FUN=mean) # NB argument name FUN is needed!
dfr
##   a f    m   m2
##   1 A  2.5  2.5
##   2 A  2.5  2.5
##   3 A  2.5  2.5
##   4 A  2.5  2.5
##   5 B  6.5  6.5
##   6 B  6.5  6.5
##   7 B  6.5  6.5
##   ...

基本包中没有什么像 ave 对于整个数据帧(AS by 就好像 tapply 对于数据帧)。但是你可以伪造它:

dfr$foo <- ave(1:nrow(dfr), dfr$f, FUN=function(x) {
    x <- dfr[x,]
    sum(x$m*x$m2)
})
dfr
##     a f    m   m2    foo
## 1   1 A  2.5  2.5    25
## 2   2 A  2.5  2.5    25
## 3   3 A  2.5  2.5    25
## ...

尽管这里有很多很棒的答案,但还有2个基本功能值得一提,有用 outer 功能和晦涩 eapply 功能

outer 是一个非常有用的功能,作为一个更平凡的功能。如果您阅读了帮助 outer 它的描述说:

The outer product of the arrays X and Y is the array A with dimension  
c(dim(X), dim(Y)) where element A[c(arrayindex.x, arrayindex.y)] =   
FUN(X[arrayindex.x], Y[arrayindex.y], ...).

这似乎使这仅对线性代数类型的事物有用。但是,它可以像 mapply 将功能应用于输入的两个向量。区别在于 mapply 将函数应用于前两个元素,然后将功能应用于第二个元素等,而 outer 将将功能应用于第一个向量的一个元素的每个组合,而从第二个矢量则将功能应用于一个元素。例如:

 A<-c(1,3,5,7,9)
 B<-c(0,3,6,9,12)

mapply(FUN=pmax, A, B)

> mapply(FUN=pmax, A, B)
[1]  1  3  6  9 12

outer(A,B, pmax)

 > outer(A,B, pmax)
      [,1] [,2] [,3] [,4] [,5]
 [1,]    1    3    6    9   12
 [2,]    3    3    6    9   12
 [3,]    5    5    6    9   12
 [4,]    7    7    7    9   12
 [5,]    9    9    9    9   12

当我有一个值的向量和条件的向量时,我亲自使用了这一点,并希望查看哪些值满足哪些条件。

eapply

eapply 就好像 lapply 除非它没有将函数应用于列表中的每个元素,它将函数应用于环境中的每个元素。例如,如果您想在全局环境中找到用户定义的功能列表:

A<-c(1,3,5,7,9)
B<-c(0,3,6,9,12)
C<-list(x=1, y=2)
D<-function(x){x+1}

> eapply(.GlobalEnv, is.function)
$A
[1] FALSE

$B
[1] FALSE

$C
[1] FALSE

$D
[1] TRUE 

坦率地说,我没有太多使用它,但是如果您要构建很多软件包或创建很多环境,它可能会派上用场。

我最近发现了相当有用的 sweep 功能并在此处添加为完整性:

基本想法是 通过阵列行或列的阵列,然后返回修改的数组。一个示例将表明这一点(来源: Datacamp):

假设您有一个矩阵,想 标准化 它的列:

dataPoints <- matrix(4:15, nrow = 4)

# Find means per column with `apply()`
dataPoints_means <- apply(dataPoints, 2, mean)

# Find standard deviation with `apply()`
dataPoints_sdev <- apply(dataPoints, 2, sd)

# Center the points 
dataPoints_Trans1 <- sweep(dataPoints, 2, dataPoints_means,"-")
print(dataPoints_Trans1)
##      [,1] [,2] [,3]
## [1,] -1.5 -1.5 -1.5
## [2,] -0.5 -0.5 -0.5
## [3,]  0.5  0.5  0.5
## [4,]  1.5  1.5  1.5
# Return the result
dataPoints_Trans1
##      [,1] [,2] [,3]
## [1,] -1.5 -1.5 -1.5
## [2,] -0.5 -0.5 -0.5
## [3,]  0.5  0.5  0.5
## [4,]  1.5  1.5  1.5
# Normalize
dataPoints_Trans2 <- sweep(dataPoints_Trans1, 2, dataPoints_sdev, "/")

# Return the result
dataPoints_Trans2
##            [,1]       [,2]       [,3]
## [1,] -1.1618950 -1.1618950 -1.1618950
## [2,] -0.3872983 -0.3872983 -0.3872983
## [3,]  0.3872983  0.3872983  0.3872983
## [4,]  1.1618950  1.1618950  1.1618950

NB:对于这个简单的示例,当然可以更轻松地实现相同的结果
apply(dataPoints, 2, scale)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top