Заполнение матрицы выводом для цикла - PullRequest
0 голосов
/ 18 апреля 2019

Я хочу заполнить матрицу данными, смоделированными с помощью цикла for, содержащего функцию rbinom. Этот цикл выполняет функцию rbinom 100 раз, таким образом генерируя различный результат при каждом запуске. Однако я не могу найти способ получить эти результаты в матрице для дальнейшего анализа. При назначении цикла для объекта этот объект выглядит пустым в среде и, следовательно, не может использоваться в матрице. ('data' должен иметь тип вектора, был 'NULL').

Если функция rbinom не включена в цикл for, ее можно назначить объекту, и я могу использовать выходные данные в матрице. Каждый столбец, однако, содержит одинаковую последовательность чисел. Когда я запускаю только цикл for, содержащий функцию rbinom, я получаю разные последовательности, так как он запускает функцию rbinom 100 раз вместо 1 раза. Я просто не знаю, как интегрировать цикл в матрицу.

Два кода, которые у меня есть:

n = 100                                                               
size = 7
loop_vill <- for (i in 1:100) {
  print(rbinom(n=n, size=size, prob=0.75))        #working for-loop                 
}


vill <- rbinom(n=n, size=size, prob=0.75)


sim_data_vill <- matrix(data=vill, nrow=length(loop_vill), ncol=100)   
#creates a matrix in which all columns are exact copies, should be solved 
when able to use outputs of loop_vill.

sim_data_vill

При вызове sim_data_vill он (логически) содержит матрицу из 100 строк и 100 столбцов, причем все столбцы совпадают. Тем не менее, я хотел бы видеть матрицу, в которой все столбцы различны (таким образом, каждый раз содержащий вывод нового запуска функции rbinom).

1 Ответ

0 голосов
/ 18 апреля 2019

Здравствуйте, насколько я вижу, у вас есть несколько проблем.

  1. В настоящее время вы не запускаете цикл for для каждого столбца (в vill) сохраняется только 1 вектор
  2. Вы не зацикливаетесь на 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, и вы начнете видеть, что накладные расходы становятся большой частью вычислений.)

Даже если это не имеет большого значения, использование векторизованных вычислений там, где они появляются,все случаи предпочтительнее, чтобы сделать код более читабельным и избежать ненужных узких мест, которые уже были оптимизированы в реализованном коде.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...