以下sas代码有什么问题?

时间:2015-03-01 08:42:40

标签: sas

我是sas的新手。我写了一个基本代码,但它没有用。有人可以帮我弄清楚代码有什么问题。我希望附加数据集。

options mprint mlogic symbolgen;
%macro temp();
%let count = 0;
%if &count = 0 %then %do;
data temp;
set survey_201106;
%let count = %eval(&count +1);
%end;
%else %do;
%do i = 201107 %to 201108;
data temp;
set temp survey_&i;
%end;
%end;
run;
%mend;
%temp;

3 个答案:

答案 0 :(得分:1)

您在宏的开头设置&count为0,因此永远不会执行%else子句。

我不确定你的目标是什么,但看起来你只想连接3个数据集并存储在新的数据集中。如果是这样,这还不够:

data temp;
    set survey_201106-survey_201108;
run;

这会创建一个名为temp的数据集,并按顺序使用survey_201106,survey_201107和survey_201108的内容填充它。 -告诉SAS您希望Survey_201106和survey_201108之间的所有数据集名为survey_20110 *。

Details of the syntax

答案 1 :(得分:0)

options mprint mlogic symbolgen;

%macro temp();

proc sql noprint;
 create table table_list as
 select monotonic() as num,memname
 from dictionary.tables
 where libname = 'WORK' and memname contains 'SURVEY_';
quit;

proc sql noprint;
 select count(*) into :cnt
 from table_list;
quit;

%do i = 1 %to &cnt.;

 %if &i eq 1 and %sysfunc(exist(work.temp)) %then %do;
   proc sql;
    drop table work.temp;
   quit;
 %end;

 proc sql noprint;
   select memname into :memname
   from table_list
   where num = &i.;
 quit;

 proc append base = temp data = &memname. force;
 run; 

%end;

%mend;

%temp;

工作:上面的代码将附加名称以?开头的所有工作数据集 '调查_'到临时数据集。

  1. dictionary.tables用于创建一个数据集,该数据集将包含名称以' survey _'。
  2. 开头的数据集列表。

    table_list数据集:

    num memname
    1   survey_201106
    2.  survey_201107
    3.  survey_201108
    
    1. 创建cnt宏变量以保存此类数据集的数量

    2. 在循环内,每个数据集呈现的数据集名称列表(在表table_list中)将附加到work.temp数据集

答案 2 :(得分:0)

您可能要做的是创建一个宏,当数据集存在时附加(由于某种原因不使用proc append),或者在数据集存在时创建它。

SAS与r或其他类似语言不同,您必须在很大程度上控制所发生的一切。 SAS的优势在于你可以要求它只使用一行或两行代码来做常见事情。由于这个原因,SAS通常被称为4th Generation Language:你不应该控制所有的小位。那是浪费时间。使用程序(PROC ...)和构建SAS为您提供。

在这种情况下,PROC APPEND完成了整个宏所做的事情。它创建一个数据集或向其添加新行(如果它已经存在)。

proc append base=temp data=in_data;
run;

现在,如果您正在尝试学习宏语言并仅将此概念用作学习工具,则可以在与您的宏不同的宏中执行此操作。

注意: 这是一个很好的方法。它可能对学习宏概念很有用,但应该用作良好代码的示例。尽管我有所改进,但仍然不是应该这样做的方式; proc append或SRSwift的例子更好。

我将在这里介绍一件事:一个宏参数。一个很好的宏编程规则是所有宏都应该有参数。如果没有可能的参数,通常应该可以不需要宏。在大多数情况下,参数是使宏有用的原因。在这种情况下,我将重写您的宏以将一个附加数据集作为参数和一个“基础”数据集。在您的示例中,temp是基础数据集,survey_1106等是附加数据集。

此外,&count必须是global宏变量。在SAS中,在宏内部创建的变量默认是在范围内本地 - 即,它们仅在宏的一次运行中定义然后消失。这几乎与c / etc中的函数相同。语言(与r有点不同,它使用词法作用域,你可能会期待你如何写这个)。虽然有一些有趣的规则,但是现在我们只是顺其自然。 global宏变量(包括已在全局范围内定义的任何变量)在所有宏迭代中(以及宏外)都可用。

所以:

%macro append_dataset(base=,append=);
 %if &count=0 %then %do;
  data &base.;
    set &append.;
  run;
 %end;
 %else %do;
  data &base.;
    set &base. &append.;
  run;
 %end;
 %let count=%eval(&count.+1);
%mend append_dataset;

%let count=0;
%append_dataset(base=temp,append=survey_1106);
%append_dataset(base=temp,append=survey_1107);
%append_dataset(base=temp,append=survey_1108);

现在,您可以通过外部方法(例如Harshad示例中的dictionary.tables)生成这些调用。您还可以向宏添加另一个元素,即迭代在append提供的列表中的所有元素。您也可以在%do循环中对列表进行硬编码,就像您在初始示例中所做的那样(但我认为这是不好的做法)。你可以在我的宏中完成这个:

%macro append_dataset(base=,append=);
 %do survey=201106 to 201108;
   %if &count=0 %then %do;
     data &base.;
       set survey_&survey.;
     run;
   %end;
   %else %do;
     data &base.;
       set &base. survey_&survey.s;
     run;
   %end;
   %let count=%eval(&count.+1);
 %end;
%mend append_dataset;

请注意,计数增量是里面 do循环 - 这是你在这里出错的地方之一。否则,这只是添加一个外部循环并将附加提及更改为循环中的计算值。但同样,这是一个相当差的编码实践 - 循环至少应该从宏参数构造。