Сбросить поток случайных чисел

Похоже, что SAS/IML имеет возможность сбросить поток случайных чисел ( ссылка на документ) .

Есть ли аналогичная функция для подпрограмм с произвольными числами на шаге данных SAS?

Исходя из этого поста, кажется, что последующие призывы к streaminit игнорируются в пределах одного шага данных.

Например, приведенный ниже код создает разные случайные числа для каждой строки:

data want;
  do i = 1 to 2;
    call streaminit(123);  * <-- WANT THIS TO RESET THE STREAM;
    ran1 = rand('uniform');      
    ran2 = rand('uniform');      
    ran3 = rand('uniform');      
    put _all_;
    output;
  end;
run;

Выход:

i=1 ran1=0.5817000773 ran2=0.0356216603 ran3=0.0781806207 
i=2 ran1=0.3878454913 ran2=0.3291709244 ran3=0.3615948586 

Я хотел бы вывод:

i=1 ran1=0.5817000773 ran2=0.0356216603 ran3=0.0781806207 
i=2 ran1=0.5817000773 ran2=0.0356216603 ran3=0.0781806207 

3 ответа

Решение

Вы не можете сбросить потоки для функции RAND в SAS 9.4M4. Однако вы можете перемотать поток в SAS 9.4M5 ( который был отправлен в сентябре 2017 года), используя новую процедуру STREAMREWIND. Следующая программа показывает синтаксис:

data want;
  call streaminit(123);  
  do i = 1 to 2;
    call streamrewind;
    ran1 = rand('uniform');      
    ran2 = rand('uniform');      
    ran3 = rand('uniform');      
    put _all_;
    output;
  end;
run;

Вы можете обойти это, используя сгенерированный код, однако, с помощью CALL EXECUTE или, возможно, DOSUBL, например:

data _null_;
  do i = 1 to 2;
    rc=dosubl(cats("data want_",i,";
    call streaminit(123);  * <-- WANT THIS TO RESET THE STREAM;
    ran1 = rand('uniform');      
    ran2 = rand('uniform');      
    ran3 = rand('uniform');    
    i=",i,"; 
    put _all_;
    output;
    run;
    "));
  end;
  rc = dosubl("data want; set want_1 want_2; run;");
run;

Очевидно, что проще / лучше написать макрос для этой части.

К сожалению, это ограничение "новой" программы RAND; со старым было намного легче работать в этом отношении (поскольку у него действительно было только одно семя). Свойства семени нового более сложны, и поэтому, хотя вы можете инициализировать его одним числом, это не так просто, отсюда и сложности.

Ты можешь использовать call ranuni использовать одно и то же начальное число для двух разных потоков случайных чисел.

Обратите внимание, что здесь используется другой, более низкий PRNG, с гораздо более коротким циклом и худшими статистическими свойствами, чем rand() функция.

Пример:

data x;
  seed1 = 123;
  seed2 = 123;
  do i =1 to 3;
    call ranuni(seed1, x); 
    call ranuni(seed2, y); 
    output;
  end;
run;

Выход:

i=1 x=0.7503960881 y=0.7503960881
i=2 x=0.3209120251 y=0.3209120251
i=3 x=0.178389649 y=0.178389649
Другие вопросы по тегам