Powtarzanie funkcji zdefiniowanej przez Użytkownika za pomocą replicate () lub sapply()
Zdefiniowałem funkcję niestandardową, taką jak:
my.fun = function() {
for (i in 1:1000) {
...
for (j in 1:20) {
...
}
}
return(output)
}
, która zwraca macierz wyjściową output
, złożoną z 1000 wierszy i 20 kolumn.
To, co muszę zrobić, to powtórzyć funkcję say 5 razy i zapisać pięć output
wyników w zupełnie nowej macierzy, powiedzmy final
, ale bez użycia innej pętli for (to dla uczynienia kodu jaśniejszym, a także dlatego, że w drugiej chwili chciałbym spróbować równoległe te dodatkowe 5 powtórzeń).
Stąd final
powinna to być macierz z 5000 wierszami i 20 kolumnami (uzasadnieniem tych 5 powtórzeń jest to, że w ramach dwóch pętli for używam między innymi funkcji sample
).
Próbowałem użyć final <- replicate(5, my.fun())
, który poprawnie oblicza pięć replikacji, ale potem muszę "ręcznie" umieścić elementy w zupełnie nowej matrycy 5000 x 20.. czy istnieje bardziej elgant sposób, aby to zrobić? (może używając sapply()
?). Wielkie dzięki
4 answers
Jak stoi prawdopodobnie macie tablicę o trzech wymiarach. Jeśli chcesz mieć listę, dodałbyś simplify = FALSE. Spróbuj tego:
do.call( rbind, replicate(5, my.fun(), simplify=FALSE ) )
Lub możesz użyć aperm
w przypadku, gdy "final" jest nadal tablicą:
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
Mogą być bardziej ekonomiczne operacje macierzy. Jeszcze nie odkryłam.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-23 23:27:11
Jeśli zamienisz replicate
na rlply z pakietu plyr
, możesz użyć do.call
z rbind
:
library(plyr)
do.call(rbind, rlply(5, my.fun()))
Jeśli wolisz nie polegać na plyr
pakiecie, zawsze możesz to zrobić:
do.call(rbind, lapply(1:5, function(i) my.fun()))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-23 22:03:38
Zależy od tego, którego pakietu używasz do obliczeń równoległych, ale oto jak to zrobię(ukryj go w pętli używając sapply
, tak jak 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()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-23 22:52:04
Spróbuj tego:
final <- replicate(5, my.fun(), simplify = "matrix")
Otrzymasz wynik 'finalny' w postaci macierzy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-10 07:30:45