Sas 保留和保留宏变量

Sas 保留和保留宏变量,sas,Sas,我有一个包含许多变量(列)的大型数据集。变量名包括 六月十九日 6月19日每单位53410实际 6月19日预算 6月19日每单位53410美元预算 六月十九日 等等。。。随着月份和账户的变化,会有数百个账户 我想写一个宏,在这个宏中,新数据集1)中包含的所有变量都是按实际顺序排列的,然后是按预算顺序排列的,并且按月交替排列,例如,新数据集 表将如下所示: JUNE19_53410_Actual JUNE19_53410_Budget AUG19_53410_Actual AUG19_

我有一个包含许多变量(列)的大型数据集。变量名包括

  • 六月十九日
  • 6月19日每单位53410实际
  • 6月19日预算
  • 6月19日每单位53410美元预算
  • 六月十九日
等等。。。随着月份和账户的变化,会有数百个账户

我想写一个宏,在这个宏中,新数据集1)中包含的所有变量都是按实际顺序排列的,然后是按预算顺序排列的,并且按月交替排列,例如,新数据集 表将如下所示:

 JUNE19_53410_Actual  JUNE19_53410_Budget   AUG19_53410_Actual AUG19_53410_Budget 
  $12,000                $34,000            $23,000            $14,000
  $13,000                $64,000            $83,000            $11,000
我尝试了下面的代码,但是当我把它放进我的数据步骤时,出现了一个错误

 %MACRO Keeping;
 retain
 &x._Actual  &x._Budget;
 keep 
 &x._Actual  &x._Budget;
 %MEND Keeping;

 data test;
 set June_2019;
 %Keeping;
 run; 

严格来说,数据集中列的顺序没有意义,除非使用任何查看器查看数据集。打印之类的过程将允许您指定订单

尽管如此,如果您确实希望保留默认顺序,如果宏变量中有所有前缀,则可以执行以下操作:

%let months = %str(JUNE19_53410 AUG19_1234);

%macro genlist;

    %let ii = 1;
    %do %while (%scan(&months, &ii, %str( )) ~= %str());
      %let col = %scan(&months, &ii, %str( ));

      &col._actual &col._budget

      %let ii = %eval(&ii + 1);
    %end;

%mend;

data want;
  retain 
    %genlist;
  ;
  set have;
  keep
    %genlist;
  ;

run;
这将按以下顺序保留以下字段:

JUNE19_53410_actual
JUNE19_53410_budget
AUG19_1234_actual
AUG19_1234_budget
如果列数太大,无法手动填充,则可能需要另一段代码来生成months宏变量。在这种情况下,您可能会超过65536的限制,并且可能必须求助于其他技术,如PROC EXECUTE。

为什么要使用宏? 使用宏“函数”的方式很难减少代码,使其更难阅读。 使用宏变量更容易

我会怎么做 您应该使用
保留
长度
还是
格式
SAS按照您提到的顺序将变量放入数据集中。
set
语句“提及”输入数据集中的所有变量,您不能再更改它们的顺序。因此,您应该在
set
语句之前提及您的变量。你有很多选择

假设您希望
a
b
成为数据集中的第一个变量,那么您有不同的选项

长度为ab8
这将
a
b
定义为数字,每个存储在8字节中(sas中数字的最大和默认长度)。您的输入数据可能具有较小的变量大小。那么这个
length
语句的副作用是,您的输出数据集将更大。没什么大不了的。 您可以对字符变量执行相同的操作,如
length first\u name last\u name$32
“保留a b;”
这避免了上述副作用,因此值得推荐。但是我避免使用它,因为它改变了SAS处理这些变量值的方式。见下文

格式a b 12.4
这说明应在12个位置打印,其中4个是小数。它隐式地将它们定义为数字,因为这是一种数字格式,长度为8字节

其他选择 您也可以在此处使用或
属性
语句

retain
做什么 通过defauls,SAS将每个观察值(即行)的所有变量设置为缺失。 Retain语句用于防止某些变量出现这种情况,如

Data running_total;
    set transactions; /* a dataset with amount */
    retain total 0;   /* initialize as 0 for the first observation */
    total = total + amount;
run;
保留总数0
保留总数的简写;如果N=1,则总数=0

在代码中,“retain”对变量的值没有影响,因为首先要做的是用
set
语句中的输入覆盖变量


但是,如果在
set
语句之前添加赋值,retain确实会影响这些变量的值。因此,我避免使用它,并对数值变量使用
length
语句。

将它们全部堆叠到一个数据集中,并添加一个指示符变量

  • SET语句上的INDSNAME存储输入数据集名称及其名称 写入输入文件变量
  • SCAN()解析不同组件的名称
  • INPUT(,Monyyy5.)尝试将月份转换为SAS日期,以便正确排序。这 可能不起作用,因为通常是标准的2019年6月与2019年6月。所以 您可以将其保留为字符,并以不同的方式进行转换

    data want;
        length source input_file $50.;
        set <list of data sets> indsname = source;
    
        input_file = source;
        month = input(scan(input_file, 2, '._'), monyy5.);
        format month monyy5.;
        code = scan(input_file, 3, '._');
        budget_actual = scan(input_file, -1, '_'); * you can recode to what you need but seems like last bit will be enough; 
    
    run;
    
    需要数据;
    源输入文件的长度为$50。;
    设置indsname=source;
    输入文件=源;
    月份=输入(扫描(输入文件,2'.'.'',周一5.);
    格式:周一至周五。;
    代码=扫描(输入_文件,3'。');
    预算_实际=扫描(输入_文件,-1,'.');*你可以重新编码到你需要的,但似乎最后一点就足够了;
    跑
    

现在,您有了一个单一的数据集,可以轻松地对所有数据进行筛选、排序、查询或按需报告。清理或重新构造数据或简单排序不再需要循环。

由于未定义宏变量x,因此出现错误。此外,您是否希望按月拆分表?是否有理由选择使用此模式(非常广泛的数据集),将日期、编号(是否是计划/商店/部门/部门?)等重要数据作为元数据和变量名的一部分?你的“问题”只会随着新月份的增加而增加。有几排?一行与另一行的区别是什么?每个数据集有多大?我可能是在打一匹死马,所以最后的回应。你真的,真的想堆叠这些数据集,并将月份和数字作为变量添加进来。这是一项耗时约5分钟的琐碎任务,使您不再需要宏和循环,并且您的代码将来会更干净、更易于管理。看起来我的帖子是由某人编辑的,他们的编辑没有反映我希望显示数据的方式,这造成了混乱!!!从那以后,我把它编辑回我原来的帖子。关于这些问题,到年底,新表I将有120列(每个月2列,每个成本中心5列,预算2列)
data want;
    length source input_file $50.;
    set <list of data sets> indsname = source;

    input_file = source;
    month = input(scan(input_file, 2, '._'), monyy5.);
    format month monyy5.;
    code = scan(input_file, 3, '._');
    budget_actual = scan(input_file, -1, '_'); * you can recode to what you need but seems like last bit will be enough; 

run;