Здравствуйте, насколько я вижу, у вас есть несколько проблем.
- В настоящее время вы не запускаете цикл for для каждого столбца (в
vill
) сохраняется только 1 вектор - Вы не зацикливаетесь на
rbinom
Теперь есть несколько способов добиться того, чего вы хотите.(Перейдите к последнему примеру, чтобы найти эффективный способ)
метод 1: For loop
Используя вашу идею, мы можем использовать for loop
.Лучше всего сначала сохранить пустую матрицу и заполнить ее for loop
nsim <- 100 #how many rbinom are w
n <- 100000
size = 7
prob = 0.75
sim_data_vill_for_loop <- matrix(ncol = nsim, nrow = n)
for(i in seq(nsim)) #iterate from 1 to nsim
sim_data_vill_for_loop[, i] <- rbinom(n, size = size, prob = prob) #fill in 1 column at a time
Теперь это будет работать, но немного медленно и требует колоссальных 3 строк кода для части моделирования!
метод 2: apply
Мы можем удалить цикл for и предварительно назначенную матрицу, используя одну из множества apply
подобных функций.Одной из таких функций является replicate
.Это сокращает огромные 3 строки кода до:
sim_data_vill_apply <- replicate(nsim, rbinom(n, size, prob))
ух ... Это было коротко, но можем ли мы сделать еще лучше?На самом деле выполнение таких функций, как rbinom
несколько раз, может быть довольно медленным и дорогостоящим.
метод 3: использование векторизованных функций (очень быстрое)
Одна вещь, которую вы услышите шепотом (или криком), этослово vectorized
, когда речь заходит о программировании на R. По сути, вызов функции вызовет издержки, и если вы работаете с векторизованной функцией, вызовите ее один раз, и убедитесь, что вы вызываете издержки только один раз, а не несколько раз.,Все функции распределения в R, такие как rbinom
, векторизованы.Так что, если мы просто сделаем все симуляцию за один раз?
sim_data_vill_vectorized_functions <- matrix(rbinom(nsim * n, size, prob), ncol = nsim, nrow = n, byrow = FALSE) #perform all simulations in 1 rbinom call, and fill in 1 matrix.
Итак, давайте просто быстро проверим, насколько быстрее это по сравнению с использованием for loop
или apply
.Это можно сделать с помощью пакета microbenchmark:
library(microbenchmark)
microbenchmark(for_loop = {
sim_data_vill_for_loop <- matrix(ncol = nsim, nrow = n)
for(i in seq(nsim)) #iterate from 1 to nsim
sim_data_vill_for_loop[, i] <- rbinom(n, size = size, prob = prob) #fill in 1 column at a time
},
apply = {
sim_data_vill_apply <- replicate(nsim, rbinom(n, size, prob))
},
vectorized = {
sim_data_vill_vectorized <- matrix(rbinom(nsim * n, size = size, prob = prob), ncol = nsim, nrow = n, byrow = FALSE)
}
)
Unit: milliseconds
expr min lq mean median uq max neval
for_loop 751.6121 792.5585 837.5512 812.7034 848.2479 1058.4144 100
apply 752.4156 781.3419 837.5626 803.7456 901.6601 1154.0365 100
vectorized 696.9429 720.2255 757.7248 737.6323 765.3453 921.3982 100
Если посмотреть на среднее время, выполнение всех симуляций за один раз составляет около 60 мс.быстрее, чем при использовании цикла for.Таким образом, здесь это не имеет большого значения, но в других случаях это может быть.(поменяйте местами n
и nsim
, и вы начнете видеть, что накладные расходы становятся большой частью вычислений.)
Даже если это не имеет большого значения, использование векторизованных вычислений там, где они появляются,все случаи предпочтительнее, чтобы сделать код более читабельным и избежать ненужных узких мест, которые уже были оптимизированы в реализованном коде.