是否可以循环遍历SAS数据集?

Bur*_*ras 10 sas sas-macro

我有60个sas数据集,其中包含有关消费者个人特征的数据,例如 id, gender, age, amountSpent, ....每个数据集仅显示一个时间段的数据(data1为Jan,data2为Feb ...).由于尺寸和其他一些问题,我无法合并它们.

如何编写多循环来遍历每个数据集,进行一些操作并将估计值保存到临时文件中.

SAS没有for循环.我该怎么用do

mvh*_*weg 7

但sas确实有一个宏循环.所以基本上你需要3件事:1.在某种程度上,你的数据集列表.2.循环遍历此列表的宏.你想做的事情.

例如,让我们假设您有一个数据集WORK.DATASET_LIST,其中包含要循环的每个数据集的变量库(libname)和变量成员(数据集名称).

然后你可以这样做:

%macro loopOverDatasets();
    /*imho good practice to declare macro variables of a macro locally*/
    %local datasetCount iter inLibref inMember;

    /*get number of datasets*/
    proc sql noprint;
        select count(*)
         into :datasetCount
        from WORK.DATASET_LIST;
    quit;

    /*initiate loop*/
    %let iter=1;
    %do %while (&iter.<= &datasetCount.);
        /*get libref and dataset name for dataset you will work on during this iteration*/
        data _NULL_;
            set WORK.DATASET_LIST (firstobs=&iter. obs=&iter.); *only read 1 record;
            *write the libname and dataset name to the macro variables;
            call symput("inLibref",strip(libname));
            call symput("inMember",strip(member));
            *NOTE: i am always mortified by the chance of trailing blanks torpedoing my code, hence the strip function;
        run;

        /*now you can apply your logic to the dataset*/
        data &inLibref..&inMember.; *assuming you want to apply the changes to the dataset itself;
            set &inLibref..&inMember.;
            /*** INSERT YOUR LOGIC HERE ***/
        run;

        /*** ANY OTHER PROCS/DATA STEPS ***/
        /*just remember to use &inLibref..&inMember. to refer to the current dataset*/

        /*increment the iterator of the loop*/
        %let iter=%eval(&iter.+1);
    %end;
%mend;

/*call the macro*/
%loopOverDatasets()
Run Code Online (Sandbox Code Playgroud)

这就是主意.也许您想以不同的方式收集数据集列表.例如,包含它们的宏变量.在这种情况下,您必须使用循环中的%扫描功能来选择数据集.或者在命名中可能存在逻辑,例如,dataset1,dataset2,dataset3 ......,在这种情况下,您可以简单地使用&iter.宏变量.


Lon*_*ish 7

另一个选择是创建一个组合所有数据集的视图,这种方法不会产生任何数据大小问题(虽然我不知道你提到的其他问题是否会成为问题).您需要一个相关数据集列表,这些数据集可以从PROC SQL中的DICTIONARY.TABLES获得.

proc sql noprint;
select memname into :ds_list separated by ' '
from dictionary.tables
where libname='XXXXX';
quit;

data combined / view=combined;
set &ds_list;
run;
Run Code Online (Sandbox Code Playgroud)

然后只针对视图运行摘要,因此无需遍历每个数据集.我假设您的数据集有一个日期变量,否则您需要添加一些额外的功能(这适用于任何解决方案).与其他解决方案相比,看看它的表现会很有趣.

  • Keith,你会(或者你介意我是否)使用`by` groups添加一些关于最终处理的指针(也许是[不要循环]的链接(http://www2.sas.com/proceedings) /forum2007/183-2007.pdf)?这会让这个答案更有用,我想. (3认同)

Joe*_*Joe 7

这就是我在日常编程中解决这个问题的方法,当需要根据数据重复调用宏时.这种方法同样适用于许多数据集或来自一个数据集的许多变量或来自一个数据集的许多不同宏调用 - 无论它们是什么,只需创建一个数据集,其中包含变化的信息并以这种方式调用它.

这种方法将Shorack解决方案的元素与user2337871和Neil's相结合.为什么不同?

  • 应该使用参数调用宏,而不是在其中包含其参数定义.这使得它在未来使用时更加灵活(例如,dataset_list数据集可能有所不同).
  • 具有基于名称数据集调用的灵活性,而不是要求宏调用宏
  • 将代码删除到宏(而不是内部call execute或其他调用方法)使其更容易阅读.
  • call execute 根据您正在进行的操作(与宏变量计时相关)可能有一些缺点

假设您正在执行PROC方式,然后将其附加到主数据集.虽然这实际上是一种非常缓慢且烦人的方式(与将它们组合在一起并使用BY,甚至将ODS OUTPUT与非组合数据集结合使用相反),我们假设您的实际任务更复杂.

%macro do_my_stuff(dataset=);
proc means data=&dataset noprint;
var count;
output out=dsn_&dataset. mean=;
run;

proc append base=results data=dsn_&dataset. force;
run;
%mend do_my_Stuff;

proc sql;
select cats('%do_my_stuff(dataset=',name,')') into :stufflist separated by ' '
from dictionary.tables
where memname='WORK';
quit;

&stufflist;
Run Code Online (Sandbox Code Playgroud)

您可以向proc sql中的where语句添加其他条件,或使用CALL EXECUTE或许多不同选项调用它.您还可以使用具有数据集名称的自制数据集(如果感兴趣的变量因数据集而异,则甚至将变量用作另一列和宏参数).