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美元预算
- 六月十九日
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;