#sas #global-variables
#sas #глобальные переменные
Вопрос:
Я хочу использовать переменные из моего списка в процедурах proc. Вот упрощенная версия моего кода.
%MACRO CORRMAKER(file,data);
%DO I=1 %TO 2;
%DO J=1 %TO 2;
data _NULL_;
ARRAY VAR1LIST[2] $ A1-A2 ('CAT11' 'CAT12');
ARRAY VAR2LIST[2] $ B1-B2 ('CAT21' 'CAT22');
%GLOBAL VAR1 VAR2;
%LET VAR1=VAR1LIST[amp;I];
%LET VAR2=VAR2LIST[amp;J];
run;
proc corr data=amp;file out=amp;dataamp;Iamp;J RANK noprob;
var INNERVAR1 INNERVAR2 INNERVAR3 INNERVAR4;
where COND1=amp;VAR1 COND2=amp;VAR2;
run;
%END;
%END;
%MEND;
Но VAR1 и VAR2 не имеют в proc соответствующей процедуры. Как я могу использовать VAR1 и VAR2?
Спасибо!
Комментарии:
1. Подсказка: это недопустимый оператор WHERE:
where cond1=VAR1LIST[1]
Ответ №1:
Я не уверен, почему вы делаете VAR1 и VAR2 глобальными, а не локальными. Похоже, что они имеют значение только внутри этого макроса. В конце макроса им просто будет присвоено последнее значение внутри %do
циклов.
Также вы, похоже, не понимаете, как работает макропроцессор. Она завершит свою работу по преобразованию триггеров макроса в текст до запуска шага сгенерированных данных. Если вы измените порядок своих инструкций, чтобы отразить это, станет понятнее, почему VAR1 и VAR2 не получают желаемых значений и почему ваш шаг данных вообще ничего не делает.
%LET VAR1=VAR1LIST[amp;I];
%LET VAR2=VAR2LIST[amp;J];
data _NULL_;
ARRAY VAR1LIST[2] $ A1-A2 ('CAT11' 'CAT12');
ARRAY VAR2LIST[2] $ B1-B2 ('CAT21' 'CAT22');
run;
Если вы действительно хотите использовать имена переменных CAT11, CAT21 и т.д., То просто создайте их из I и J.
%let var1=cat1amp;i;
%let var2=cat2amp;j;
Если у вас действительно есть списки имен переменных, поместите списки в макропеременные.
%let varlist1=cat11 cat12;
%let varlist2=cat21 cat22;
%let var1=%scan(amp;varlist1,amp;i);
%let var2=%scan(amp;varlsit2,amp;j);
Ваш оператор WHERE также выглядит неправильно. Возможно, вы имели в виду что-то более похожее:
%let values1 = cat11 cat12 ;
%let values2 = cat21 cat22 ;
%do i=1 %to 2 ;
%do j=1 %to 2 ;
....
where cond1="%scan(amp;values1,amp;i)" and cond2="%scan(amp;values2,amp;j)";
....
%end;
%end;
Комментарии:
1. Большое вам спасибо! На самом деле, мой VAR1LIST состоит из массива chacter типа (‘cat’, ‘dog’, ‘horse’), которые не представлены в виде текста чисел. Мне следовало спросить более конкретно, и вы любезно ожидали моей ситуации. Как вы сказали, это не было проблемой глобальной переменной. Спасибо!
Ответ №2:
Макросы не имеют собственной конструкции массива. Термин «массив макросов» является метафорой для случая области, имеющей доступ к N макропеременным с одинаковым базовым именем и последовательными (или индексными) суффиксами. Вы можете напрямую назначить каждой переменной, которая действует как элемент массива, или у вас может быть какой-нибудь изящный код, который выделяет переменные из текстового списка.
«Индексированные» переменные разрешаются в цикле с использованием конструкции amp;amp;amp;. Например:
%let A2 = 1234;
%let index = 2;
%let var1 = amp;amp;Aamp;index; %* var1 gets 1234;
Часть обязанностей супервизоров SAS заключается в неявном разрешении макроображений, повторяя токен по мере необходимости. Удвоенные значения amp; ‘s уменьшаются вдвое на каждой итерации неявного разрешения. Например:
amp;amp;Aamp;index -> amp;A2 -> 1234
Ваш код может измениться на
%MACRO CORRMAKER(file,data);
%local A1 A2 B1 B2 I J VAR1 VAR2;
%let A1 = CAT11;
%let A2 = CAT12;
%let B1 = CAT21;
%let B2 = CAT22;
%DO I=1 %TO 2;
%DO J=1 %TO 2;
%LET VAR1=amp;amp;Aamp;I;
%LET VAR2=amp;amp;Bamp;J;
proc corr data=amp;file out=amp;dataamp;Iamp;J RANK noprob;
var INNERVAR1 INNERVAR2 INNERVAR3 INNERVAR4;
where COND1="amp;VAR1" and COND2="amp;VAR2";
run;
%END;
%END;
%MEND;
Комментарии:
1. На самом деле, у меня есть реальный список переменных, которые не представлены в виде текста числа. Мне следовало спросить более конкретно. Но ваш ответ очень помог мне понять структуру макросов SAS. Спасибо!