2013-09-03 2 views
2

В Stata вы можете перебирать список значений символов с помощью foreach command. Я пытался сделать то же самое в SAS до сих пор. Я пытаюсь запустить серию данных и proc-операторов по всем значениям столбца символов. Я пробовал с:Зацикливание символьных значений в SAS

%let mylist = a b c; * These are all the values of a column called "code"; 

data [email protected]; * Each element creates a new table;  
    set mydata; 
    where code=&mylist; 
    run; 

Что я делаю неправильно или не хватает?

Спасибо заранее,

Матиас

ответ

4

Попробуйте это:

%macro loopit(mylist); 
    %let n = %sysfunc(countw(&mylist)); 
    %do I=1 %to &n; 
     %let val = %scan(&mylist,&I); 

     data mydata_&val; 
     set mydata; 
     where code = "&val"; 
     run; 
    %end; 
%mend; 

%let list=a b c; 
%loopit(&list); 
+0

Это ошибка, если пользователь передает нулевой список. Задание разделителя позволяет COUNTW возвращать 0:% sysfunc (countw (& mylist,% STR())) – Quentin

1

Модифицированная версия основана на том, что DomPazz при условии:

data mydata; 
length code $8; 
input code; 
cards; 
a 
a 
b 
c 
n 
; 
run; 

%macro loopit(mylist); 
    %let else=; 
    %let n = %sysfunc(countw(&mylist)); 
    data 
    %do I=1 %to &n; 
     %let val = %scan(&mylist,&I); 
     mydata_&val 
    %end; 
     other 
     ; 


     set mydata; 
    %do j=1 %to &n; 
     %let val = %scan(&mylist,&j); 
     %if &j ne 1 %then %do; 
     %let else=else; 
     %end; 
     &else if code = "&val" then output mydata_&val; 
     %if &j = &n %then %do; 
     else output other; 
     %end; 
    %end; 
    run; 
%mend; 

options mprint; 
%let list=a b c; 
%loopit(&list); 

Здесь я обрабатываю входные данные только один раз (для эффективности, если вам нужно), создавая все выходные таблицы на одном шаге данных. Также я создаю таблицу «Другие». Чтобы обрабатывать только записи с кодом из списка, вы можете добавить инструкцию WHERE в инструкции SET и опустить другой вывод другой;

+0

определенно более эффективно, если mydata велико или у вас есть большое количество идентификаторов для фильтрации. – DomPazz

+0

Большое спасибо, DomPazz и vasja! Решение, предлагаемое vasja, похоже, работает, но у меня все еще есть проблемы с некоторыми элементами столбца символов, которые включают тире («-»), которые SAS разделяют на два элемента. Любое предложение? –

0
%macro getName; 
%let name = %sysfunc(translate(&val, __, -/)); 
%mend; 

%macro loopit(mylist); 
    %let else=; 
    %let name=; 
    %let n = %sysfunc(countw(&mylist, %str())); 
    data 
    %do I=1 %to &n; 
     %let val = %scan(&mylist,&I, %str()); 
     %getName 
     mydata_&name 
    %end; 
     other 
     ; 


     set mydata; 
    %do j=1 %to &n; 
     %let val = %scan(&mylist,&j, %str()); 
     %getName 
     %if &j ne 1 %then %do; 
     %let else=else; 
     %end; 
     &else if code = "&val" then output mydata_&name; 
     %if &j = &n %then %do; 
     else output other; 
     %end; 
    %end; 
    run; 
%mend; 

options mprint; 
%let list=a-a b/b c-; 
%loopit(&list); 

Эта версия использует COUNTW и SCAN функции с модификаторами только использовать пространство (%str()) как разделитель слов.

использует также новый макрос getName сочинить имя для набора данных в соответствии с SAS правила именования (обратите внимание %let name = ; просто обеспечить переменную внутри %loopit для %getName для заполнения).

%getName переводит недопустимые символы для подчеркивания (здесь возникает конфликт имен имен, если у вас одинаковые значения с другим разделителем).

Смежные вопросы