2015-02-19 8 views
0

Надеюсь, простой ответ. Я занимаюсь симуляционным исследованием, где мне нужно пробовать случайное число индивидуумов N из равномерного распределения U (25,200) при каждой из тысячи повторений. Код для одной репликации показан ниже:Холдинг сэмплированный макрос переменная константа

%LET U = RAND("UNIFORM"); 
%LET N = ROUND(25 + (200 - 25)*&U.); 

Я создал оба этих макропеременные вне шага DATA, потому что мне нужно вызвать переменную N раза на последующих стадиях DATA и DO петли как в SAS и IML.

Проблема заключается в том, что каждый раз, когда я вызываю N в репликации, он повторно выбирает U, который обязательно изменяет N. Таким образом, N не поддерживается постоянной в репликации. Эта проблема показана в приведенном ниже коде, где я сначала создаю N как переменную (постоянную для отдельных лиц) и значения прогностического образца для X для каждого человека, используя цикл DO. Обратите внимание, что значение в N не совпадает с общим количеством лиц, что также является проблемой.

DATA ID; 
    N = &N.; 
    DO PersonID = 1 TO &N.; 
     X = RAND("NORMAL",0,1); OUTPUT; 
    END; 
RUN; 

Я предполагаю, что мне нужно сделать, это каким-то образом держать постоянную U на протяжении всей полноте одной репликации, а затем позволить ему быть повторно пробы для репликации 2, и так далее. Удерживая константу U, N обязательно будет оставаться постоянной.

Есть ли способ сделать это с помощью макропеременных переменных?

ответ

0

&N не сохраняет значение. &N хранит код «ROUND (... (RAND ...» и т. Д. Вы неправильно используете макропеременные, здесь: пока вы можете сохранить номер в &N, вы этого не делаете, вы должны использовать %sysfunc, и либо как это не совсем правильный ответ здесь.

во-первых, если вы повторно выборки повторах, посмотрите на бумаге Don't be Loopy', которая имеет некоторые приложения здесь. Также рассмотрим статью Рик Wicklin в, Sampling with Replacement, и его книгу, которую он ссылается («Имитация данных в SAS») тоже неплохо. Если вы используете свой процесс на модели с одним образцом одного исполнения, это медленный и трудный для работы. Все репликации сразу, обработайте их все сразу, IML и SAS с удовольствием сделают это для вас. С вашей формой случайной выборки немного труднее работать, но это не является непреодолимым.

Если вы должны сделать это так, как вы это делаете, я бы попросил шаг данных создать макро переменную, если есть повод сделать это. В конце образца, вы можете использовать call symput гасить значение N. IE:

%let iter=7; *we happen to be on the seventh iteration of your master macro; 
DATA ID; 
    CALL STREAMINIT(&iter.); 
    U = RAND("UNIFORM"); 
    N = ROUND(25 + (200 - 25)*U); 
    DO PersonID = 1 TO N; 
     X = RAND("NORMAL",0,1); 
     OUTPUT; 
    END; 
    CALL SYMPUTX('N',N); 
    CALL SYMPUTX('U',U); 
RUN; 

Но опять же, один-данных шаг модель, вероятно, ваша самая эффективная модель.

+0

Спасибо, Джо! И, да, мой процесс моделирования неуклюж. Для меня это разница между 5 и 10 минутами. Дает мне некоторое время, чтобы выбраться со стула и немного погулять. :) –

0

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

Ключ устанавливает значение инициализации случайного числа, используя CALL STREAMINIT.

Data _null_; 
call streaminit(35); 
u=rand('uniform'); 
call symput('U', u); 
call symput('N', ROUND(25 + (200 - 25)*U)); 
run; 


%put &n; 
%put &u; 
+0

Хотя CALL STREAMINIT - отличная идея, в его случае это не проблема: проблема в его коде: 'make PersonID = 1 to ROUND (25+ (200- 25) * RAND ('UNIFORM')); 'который каждый раз создает контур цикла с новым значением. – Joe

0

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

data AllSamples; 
call streaminit(123); 
do SampleID = 1 to 1000; 
    N = ROUND(25 + (200 - 25)*RAND("UNIFORM")); 
    /* simulate sample of size N HERE */ 
    do PersonID = 1 to N; 
     X = RAND("NORMAL",0,1); 
     OUTPUT; 
    end; 
end; 
run; 

Это обеспечивает независимость случайное число потоков, и он принимает доли секунды для получения 1000 образцов.Затем вы можете использовать оператор BY для анализа выборочных распределений статистики по каждому образцу. Например, следующий вызов PROC ОЗНАЧАЕТ выводит размер выборки, выборочное среднее и выборочное стандартное отклонение для каждого из 1000 образцов:

proc means data=AllSamples noprint; 
by SampleID; 
var X; 
output out=OutStats n=SampleN mean=SampleMean std=SampleStd; 
run; 

proc print data=OutStats(obs=5); 
var SampleID SampleN SampleMean SampleStd; 
run; 

Для более подробной информации о том, почему BY-групповой подход является более эффективным (всего время = менее 1 секунды!) см. статью "Simulation in SAS: The slow way or the BY way."