我有一个大型数据集,其中包含许多变量(列)。变量名称包括
依此类推...随着月份和帐户的更改,有数百种。
我想编写一个MACRO,其中新数据集中包含的唯一变量1)的顺序为Acutal,然后按Budget,然后按月交替,例如, 表格如下:
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;
答案 0 :(得分:2)
您使用宏“函数”的方式几乎不会减少代码,也很难阅读。 使用宏变量更容易。
/* List the variables you want */
%let myVars =
JUNE19_53410_Actual JUNE19_53410_Budget
AUG19_53410_Actual AUG19_53410_Budget
...
DEC19_53410_Actual DEC19_53410_Budget
;
/* Define what dataset you create */
data want;
/* I specify the order of the variables with a length statement */
length &myVars 8;
/* Read in your data */
set have;
/* keep only what you need */
keep &myVars;
run;
retain
,length
还是format
SAS按照您提到变量的顺序将变量放入数据集中。 set
语句“提及”输入数据集中的所有变量,您无法再更改其顺序。因此,您应该在set
语句之前提及变量。您有很多选择。
假设您希望a
和b
成为数据集中的第一个变量,那么您有不同的选择
length a b 8;
这将a
和b
定义为数字,每个以8字节存储(数字的最大和默认长度,以sas为单位)。您的输入数据的变量大小可能较小。然后,此length
语句的副作用是输出数据集将更大。没什么大不了的。
您可以对length first_name last_name $32;
中的字符变量执行相同的操作,但这会带来更大的风险:如果这些变量在输入数据集上较长,则可能会截断它们。
这避免了上述副作用,因此SAS建议使用。但是,我避免这样做,因为它改变了SAS处理这些变量值的方式。见下文。
format a b 12.4;
此选项应在12个位置打印,其中4个为小数。它隐式地将它们定义为数字,因为这是数字格式,并且长度默认为8个字节。
您还可以在此处使用label
或attribute
语句。
retain
的作用通过默认设置,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;
retain total 0;
是retain total; if _N_ = 1 then total = 0;
的简写
在您的代码中,“保留”对变量的值没有影响,因为您要做的第一件事就是用set
语句中的输入覆盖它们。
但是,如果在set
语句之前添加分配,则保留确实会影响这些变量的值。因此,我避免使用它,而对数字变量使用length
语句。
答案 1 :(得分:1)
严格来说,除非使用任何查看器查看数据集,否则数据集中列的顺序没有意义。像PRINT这样的PROC可以让您指定顺序。
尽管如此,如果您确实想保留默认顺序,则可以在宏变量中包含所有前缀的情况下执行以下操作:
%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等其他技术。
答案 2 :(得分:1)
将它们全部堆叠到一个数据集中,并添加一个指标变量。
INPUT(,monyy5。)尝试将月份转换为SAS日期,以便正确排序。这个 可能不起作用,因为您通常使用标准的JUNE2019 vs JUN2019。所以 您可以保留其特征并以其他方式进行转换。
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;
现在,您只有一个数据集,可以轻松过滤,排序,查询或将所有数据用于按需报告。不再需要清洗或重组数据或简单排序的循环。