使用replicate()或sapply()重复一个用户定义的函数

10

我定义了一个自定义函数,就像这样:

my.fun = function() {

      for (i in 1:1000) {
      ...
        for (j in 1:20) {
          ...
        }
      }

 return(output)

}

该函数返回一个由1000行和20列组成的输出矩阵output

我的任务是将该函数重复执行5次,并将这五个output结果存储到一个全新的矩阵中,例如final,但是不使用另一个for循环(这样可以使代码更清晰,并且在稍后我想尝试并行化这5个重复)。

因此,final应该是一个具有5000行和20列的矩阵(进行这5次重复的原理是在我使用的两个for循环中,除了其他函数之外,还使用了sample函数)。

我尝试使用final <- replicate(5, my.fun()),它正确计算了五个复制,但然后我必须“手动”将元素放入一个全新的5000 x 20矩阵中.. 是否有一种更优雅的方法来做到这一点?(也许使用sapply()?)非常感谢

4个回答

14

目前您可能拥有一个三维数组。如果您想要一个列表,可以添加simplify=FALSE。尝试这样做:

do.call( rbind, replicate(5, my.fun(), simplify=FALSE ) )

或者你可以在“final”仍然是数组的情况下使用aperm

fun <- function() matrix(1:10, 2,5)
final <- replicate( 2, fun() )
> final
, , 1

     [,1] [,2] [,3] [,4] [,5]
[1,]    1    3    5    7    9
[2,]    2    4    6    8   10

, , 2

     [,1] [,2] [,3] [,4] [,5]
[1,]    1    3    5    7    9
[2,]    2    4    6    8   10

> t( matrix(aperm(final, c(2,1,3)), 5,4) )
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    3    5    7    9
[2,]    2    4    6    8   10
[3,]    1    3    5    7    9
[4,]    2    4    6    8   10

可能存在更经济的矩阵运算方式,但我目前还未发现。


非常感谢您的帮助。顺便说一下,关于三维数组,您是正确的 :) - Stefano Lombardi

7

如果您使用plyr包中的rlply替换replicate,则可以使用do.callrbind

library(plyr)
do.call(rbind, rlply(5, my.fun()))

如果你不想依赖于plyr包,你可以采用以下方式:

do.call(rbind, lapply(1:5, function(i) my.fun()))

7

根据你使用的并行计算程序包不同,但这是我会做的方式(将其隐藏在循环中使用sapply,就像replicate一样)。

library(snowfall)
sfInit(parallel = TRUE, cpus = 4, type = "SOCK")
# sfExport() #export appropriate objects that will be needed inside a function, if applicable
# sfLibrary() #call to any special library
out <- sfSapply(1:5, fun = my.fun, simplify = FALSE)
sfStop()

非常感谢,这非常有趣。顺便说一下,我计划使用 snowfall - Stefano Lombardi

0

试试这个:

final <- replicate(5, my.fun(), simplify = "matrix")

你将以矩阵的形式获得“final”的结果。


我认为simplify只能接受FALSETRUE"array"。默认的TRUE会返回一个向量或矩阵(如果适用)。 - Valentin_Ștefan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接