使用sapply还是Vector?

时间:2019-01-25 14:27:22

标签: r sapply

我是R的新手,我发现应该使用向量作为调用函数的参数还是使用sapply将向量中的变量逐个赋予函数的模棱两可。

不是同一回事吗?如果同一件事,为什么sapply存在?是否有时我应该使用一种方法或另一种方法,以及如何知道使用哪种方法?

这个问题浮现在我的脑海,因为我正在写这个

sapply(1:3, function(i) dnorm(i,0,1))

然后我偶然发现自己可以做

dnorm(1:3,0,1)

如果我不是偶然发现它(为了不对其他功能犯同样的错误),我怎么知道呢?

发现我尝试以与此代码相同的方式进行更改

kappa <- c(1,2,3,4,5,6,7)

sapply(kappa, function(t) 
  optimize(function(x) (t*x^22+5*x+6), c(-10,10))$minimum)

对此

kappa <- c(1,2,3,4,5,6,7)

  optimize(function(x) (kappa*x^22+5*x+6), c(-10,10))$minimum

但是没有用!

请给我一个很好的解释。

谢谢

2 个答案:

答案 0 :(得分:3)

从根本上讲,sapply和它的 apply 家族的同级兄弟是构建矢量/矩阵或从多项目对象列表的循环。请参阅以下主题的规范答案:Is the "*apply" family really not vectorized?。但是,某些操作是矢量化的(即,循环是在计算机级别(例如,在C或Fortran中)运行的,并且可以接收矢量或列表,并且可以非常快速地运行。

几乎总是,非循环版本将运行得更快。下面显示了更大的序列输入的时序。

system.time({sapply(1:300000, function(i) dnorm(i,0,1))})
#    user  system elapsed 
#   1.097   0.026   1.169

system.time({dnorm(1:300000,0,1)})
#    user  system elapsed 
#   0.006   0.001   0.007

您发现dnorm是这样的向量化函数。许多R函数可以接受向量或列表以返回相等长度的输出,包括pastelengthstoupper[file.*系列,as.*家庭,grep家庭。但是,更复杂的多层操作需要迭代调用才能返回使用optim发现的单个对象。其他非矢量化方法包括read.csvwrite.csvmergelmglmsummary。通过这些方法, apply 系列可以迭代调用它们,并将所有元素绑定到单个对象中,例如vector / matrix或list。

kappa <- seq(1,7)

sapply(kappa, function(i) optimize(function(x) (i^x^2+5*x+6), c(-10,10))$minimum)
# [1] -9.9999263 -1.2407389 -0.9122106 -0.7784485 -0.7022782 -0.6517733 -0.6151620

答案 1 :(得分:1)

通常,当您拥有向量时,应始终使用类似dnorm(1:3,0,1)的语法,而不是sapply。它只是更快,更优雅。唯一的例外是当您使用的函数未向量化时(帮助页面中指出,参数应为单个字符/数字,或者这是您自己知道的函数未向量化的函数)。

sapply非常适合列表:

> sapply(list(c(1:5), 5), sum)
[1] 15  5
> sum(list(c(1:5), 5))
Error in sum(list(c(1:5), 5)) : invalid 'type' (list) of argument

对于矩阵,apply

> apply(matrix(1:4, 2, 2), 1, sum)
[1] 4 6
> apply(matrix(1:4, 2, 2), 2, sum)
[1] 3 7
> sum(matrix(1:4, 2, 2))
[1] 10

正如@davide在评论中所说,optimize并不将向量作为输入。