使用 sapply 还是 Vector?
Use sapply or Vector?
我是 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
但是没用!
拜托,我需要一个很好的解释。
谢谢
一般来说,当你有一个向量时,你应该总是使用类似 dnorm(1:3,0,1)
的语法而不是 sapply
。它只是更快,更优雅。唯一的例外是当您使用的函数未矢量化时(在帮助页面中说明参数应该是单个 character/number 或者这是您自己的函数,您知道该函数未矢量化)。
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
不将矢量作为输入。
从根本上说,sapply
以及它在 apply 系列中的兄弟姐妹,都是构建 vector/matrix 或多项列表的循环目的。请参阅有关主题的规范答案:。然而,一些操作是矢量化的(即,循环是 运行 在机器级别,例如在 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 函数可以接受 return 等长输出的向量或列表,包括 paste
、lengths
、toupper
、[
、file.*
系列、as.*
家庭,grep
家庭。然而,更复杂的多层操作需要迭代调用 return 单个对象,正如您在 optim
中发现的那样。其他非矢量化方法包括 read.csv
、write.csv
、merge
、lm
、glm
和 summary
。使用这些方法,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
我是 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
但是没用!
拜托,我需要一个很好的解释。
谢谢
一般来说,当你有一个向量时,你应该总是使用类似 dnorm(1:3,0,1)
的语法而不是 sapply
。它只是更快,更优雅。唯一的例外是当您使用的函数未矢量化时(在帮助页面中说明参数应该是单个 character/number 或者这是您自己的函数,您知道该函数未矢量化)。
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
不将矢量作为输入。
从根本上说,sapply
以及它在 apply 系列中的兄弟姐妹,都是构建 vector/matrix 或多项列表的循环目的。请参阅有关主题的规范答案:
几乎总是,非循环版本 运行 更快。下面显示了更大序列输入的时序。
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 函数可以接受 return 等长输出的向量或列表,包括 paste
、lengths
、toupper
、[
、file.*
系列、as.*
家庭,grep
家庭。然而,更复杂的多层操作需要迭代调用 return 单个对象,正如您在 optim
中发现的那样。其他非矢量化方法包括 read.csv
、write.csv
、merge
、lm
、glm
和 summary
。使用这些方法,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