ste*_*ejb 15 r function lapply
我经常想做以下几点:
mat <- matrix(0,nrow=10,ncol=1)
lapply(1:10, function(i) { mat[i,] <- rnorm(1,mean=i)})
Run Code Online (Sandbox Code Playgroud)
但是,我希望mat里面会有10个随机数,但它有0个.(我并不担心rnorm部分.显然有一种正确的方法可以做到这一点.我担心会影响mat lapply的匿名函数)我可以不从lapply里面影响矩阵垫吗?为什么不?是否有R的范围规则阻止了这个?
Sha*_*ane 28
我在这个相关的问题中讨论了这个问题:" R是否适用于家庭而不是语法糖 ".您会注意到,如果您查看函数签名for for和apply,它们有一个关键区别:for循环计算表达式,而apply循环计算函数.
如果你想改变apply函数范围之外的东西,那么你需要使用<<-或assign.或者更重要的是,使用类似for循环的东西.但是,在处理函数之外的事情时,您确实需要小心,因为它可能导致意外行为.
在我看来,使用apply函数的一个主要原因是明确的,因为它不会改变它之外的东西.这是函数式编程的核心概念,其中函数避免了副作用.这也是为什么apply函数族可以用于并行处理(并且类似的函数存在于诸如雪的各种并行包中)的原因.
最后,运行代码示例的正确方法是将参数传递给函数,并分配输出:
mat <- matrix(0,nrow=10,ncol=1)
mat <- matrix(lapply(1:10, function(i, mat) { mat[i,] <- rnorm(1,mean=i)}, mat=mat))
Run Code Online (Sandbox Code Playgroud)
在可能的情况下(因此mat=mat)最好明确参数,而不是推断它.
高阶函数的主要优点之一是,lapply()或者sapply()您不必初始化"容器"(在这种情况下为矩阵).
正如Fojtasek建议的那样:
as.matrix(lapply(1:10,function(i) rnorm(1,mean=i)))
Run Code Online (Sandbox Code Playgroud)
或者:
do.call(rbind,lapply(1:10,function(i) rnorm(1,mean=i)))
Run Code Online (Sandbox Code Playgroud)
或者,简单地作为数字向量:
sapply(1:10,function(i) rnorm(1,mean=i))
Run Code Online (Sandbox Code Playgroud)
如果您真的想要修改匿名函数范围之上的变量(在此实例中为随机数生成器),请使用 <<-
> mat <- matrix(0,nrow=10,ncol=1)
> invisible(lapply(1:10, function(i) { mat[i,] <<- rnorm(1,mean=i)}))
> mat
[,1]
[1,] 1.6780866
[2,] 0.8591515
[3,] 2.2693493
[4,] 2.6093988
[5,] 6.6216346
[6,] 5.3469690
[7,] 7.3558518
[8,] 8.3354715
[9,] 9.5993111
[10,] 7.7545249
Run Code Online (Sandbox Code Playgroud)
见这个职位有关<<-.但是在这个特定的例子中,for循环会更有意义:
mat <- matrix(0,nrow=10,ncol=1)
for( i in 1:10 ) mat[i,] <- rnorm(1,mean=i)
Run Code Online (Sandbox Code Playgroud)
i在全局工作空间中创建索引变量的次要成本.