Do l oop в макросе SAS - PullRequest
       28

Do l oop в макросе SAS

2 голосов
/ 23 апреля 2020

Я пытаюсь создать макрос, который будет перебирать строковые значения столбца.

Вот данные:

SUBJECT          VISIT            PARAMETER
001              Baseline         param1
001              Visit 2          param1
001              Visit 3          param1
001              Baseline         param2
001              Visit 2          param2
001              Visit 3          param2
002              Baseline         param1
002              Visit 2          param1
002              Visit 3          param1
002              Baseline         param2
002              Visit 2          param2
002              Visit 3          param2

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

%macro want(numb, string);

DATA want&numb;
   SET have;
   IF parameter = &string;
RUN;

%mend want;

В его текущей форме я должен ввести оба числа и строковое значение в столбце PARAMETER. Я хотел бы изменить макрос так, чтобы я мог перебирать 30 параметров, а не следующее:

%want(1, 'param1');
%want(2, 'param2');
...
%want(30, 'param30');

Любое понимание будет высоко оценено.

Ответы [ 2 ]

3 голосов
/ 25 апреля 2020

Если вы хотите передать несколько значений в вызов макроса, то обычно проще всего использовать список с разделителями. Макрос может использовать функцию макроса %SCAN() для выбора отдельных значений, если он этого хочет. Вы можете использовать функцию COUNTW() для определения количества значений. Оберните его в макрос функции %SYSFUNC(), чтобы использовать его в макросе c.

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

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

%macro split(inds,prefix,values);
%local i n dsname sep;
%let n=%sysfunc(countw(&values,%str( ),q));
data 
%do i=1 %do &n;
  %let dsname=&prefix.&n;
  &dsname.
%end;
;
  set &inds ;
%do i=1 %to &n;
  %let dsname=&prefix.&n;
  &sep. if parameter = %scan(&values,&i,q) then output &dsname.;
  %let sep=else;
%end;
run;
%mend ;

Итак, ваш пример будет вызовом, подобным этому:

%split(inds=have,prefix=want,values='param1' 'param2' ... 'param30')

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

proc sql noprint;
  select distinct quote(trim(param),"'") into :parmlist separated by ' '
  from list_of_parameters
  ;
quit;

И использовать эту макропеременную в вызове.

 %split(inds=have,prefix=want,values=&parmlist.)

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

Обратите внимание , что в общем случае нет необходимости разбивать набор данных нравится. Если вы хотите использовать исходный набор данных HAVE, но использовать наблюдения только для определенного значения PARAMETER, просто используйте оператор WHERE или WHERE = набор данных.

0 голосов
/ 25 апреля 2020

Этот код работает как решение:

%macro want();
data _null_;
  set HAVE;
  call symput('lengthmac',_N_);
run;


%do i = 1 %to &lengthmac;
data _null_;
  set have;
  IF _N_ = &i;
  call symput('parammac',parameter);
run;

data want&i;
   SET have;
   IF PARAM = "&parammac";
run;
%end;

%mend want;
...