Постоянная переменная макроса
Надеюсь, простой ответ. Я провожу симуляционное исследование, в котором мне нужно выбрать случайное число индивидуумов, 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 обязательно будет оставаться постоянным.
Есть ли способ сделать это с помощью макропеременных?
3 ответа
&N
не хранит значение. &N
сохраняет код "ROUND(...(RAND..." и т. д.). Вы неправильно используете макропеременные, здесь: в то время как вы могли бы сохранить число в &N
ты этого не делаешь; ты должен использовать %sysfunc
и в любом случае это не совсем правильный ответ здесь.
Во-первых, если вы неоднократно пробуете реплики, посмотрите на статью " Не будь дураком", в которой есть некоторые приложения. Также рассмотрите статью Рика Уиклина " Выборка с заменой" и его книгу, на которую он ссылается ("Моделирование данных в 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;
Но опять же, модель с одним шагом данных, вероятно, является вашей наиболее эффективной моделью.
Я не уверен, как это сделать в макромире, но именно так вы можете преобразовать свой код в шаг данных, чтобы выполнить то же самое.
Ключ устанавливает значение инициализации потока случайных чисел, используя 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;
Как указывает Джо, эффективный способ выполнить это моделирование - сгенерировать все 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 MEANS выводит размер выборки, среднее значение выборки и стандартное отклонение выборки для каждой из 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-group более эффективен (общее время = менее 1 секунды!), См. Статью "Моделирование в SAS: медленный путь или путь BY".