SAS:首先使用。最后的。在 %if 在 %macro 中
SAS: using first. last. in %if in %macro
我正在尝试为数字变量构建容器。
当我没有使用 %macro 时一切正常,因此我相信它是特定于宏的。基本上这部分代码:
%if first.&rank_column. = 1 %then %do;
没有像我预期的那样工作。下面我简化为只有一次迭代和一个变量,但我的实际代码有更多 - 但是问题是一样的。
完整代码:
/* Build binns */
%let var_list = MSRP Invoice;
%macro group_var_in_bins(source_table);
data WITH_BINNS;
set &source_table.;
run;
%let loop_count = %sysfunc(countw(&var_list));
%do i=1 %to &loop_count.;
* list of variables to use;
%let variable = %scan(&var_list, &i);
%let rank_column = &variable._bins_rank;
proc rank data=WITH_BINNS out=WITH_BINNS groups=10 ties=low;
var &variable.;
ranks &rank_column.;
run;
* sort the table by this variable;
proc sort data=WITH_BINNS out=WITH_BINNS;
by &variable.;
run;
* Build start and end observation of particular bin;
data WITH_BINNS;
set WITH_BINNS;
by &rank_column.;
*this is just to check if first.&rank_column works;
first_&rank_column. = first.&rank_column.;
last_&rank_column. = last.&rank_column.;
%if first.&rank_column. = 1 %then %do;
/* here %if first.&rank_column. %then %do erros so something is wrong with argument statement*/
Start_bin = &variable.;
%end;
%else %do;
Start_bin = .;
%end;
%if last.&rank_column. = 1 %then %do;
End_bin = &variable.;
%end;
%else %do;
End_bin = .;
%end;
run;
%end;
* some more code which amends WITH_BINNS table;
%mend group_var_in_bins;
%group_var_in_bins(sashelp.cars);
结果如下:
因此循环无法识别 %if 部分中的参数。
感谢帮助!!
[编辑]:
澄清一下,我要执行的步骤是:
列表中的变量 &var_list。
为其建立排名
按该变量排序
逐步使用数据:按排名分组
找到这个变量的值,它对应于使用 first 的组的开始。并使用 last 结束组的结束。剩下的留空
一些后续步骤...
所以基本上我想创建排名间隔的乞讨和结束。
我以图片为例;第一行有第一个。 = 1 因此 Start_bin 应该是 $10.280 而 End_bin 应该是空的。下一行应该是空的,因为两者都在前。最后。是 0。
所以你的基本问题是你在应该使用普通逻辑的地方使用了宏逻辑。
%if first.&rank_column. = 1 %then %do;
永远不会为真,即使 rank_column
为空,因为字符串 first.
永远不会等于字符串 1
.
但是如果您使用 SAS 代码而不是宏代码对其进行编码
if first.&rank_column. = 1 then do;
那么,当您第一次观察到由宏变量 rank_column
.
的值命名的变量的特定值时,它将为真
您的整体逻辑可能存在更大的问题,因为您在同一数据集中覆盖了相同的变量名称 start_bin
和 end_bin
。因此只有您的列表的最后一个变量生成的 bin 的值在宏完成后才可用。
如果您最终要查找 bin 边界,groups=10,这是否等同于通过 proc summary 或 proc means 查找百分位数?通过百分位数方法进行操作的好处还意味着您可以一次处理多个变量。我没有在这里设置任何领带选项,但我相信也可以设置。
ods select none; /*do not display output - faster processing*/
proc means data=sashelp.cars /*input data set*/
stackods /*stack ods to have the table appear with statistics across the top*/
N NMISS Min P10 P20 P30 P40 P50 P60 P70 P80 P90 Max /*stats to show*/;
var mpg_city mpg_highway invoice msrp; /*variables included in analysis*/
ods output summary = want; /*capture output into a data set*/
run;
ods select all; /*reset output options*/
我正在尝试为数字变量构建容器。 当我没有使用 %macro 时一切正常,因此我相信它是特定于宏的。基本上这部分代码:
%if first.&rank_column. = 1 %then %do;
没有像我预期的那样工作。下面我简化为只有一次迭代和一个变量,但我的实际代码有更多 - 但是问题是一样的。
完整代码:
/* Build binns */
%let var_list = MSRP Invoice;
%macro group_var_in_bins(source_table);
data WITH_BINNS;
set &source_table.;
run;
%let loop_count = %sysfunc(countw(&var_list));
%do i=1 %to &loop_count.;
* list of variables to use;
%let variable = %scan(&var_list, &i);
%let rank_column = &variable._bins_rank;
proc rank data=WITH_BINNS out=WITH_BINNS groups=10 ties=low;
var &variable.;
ranks &rank_column.;
run;
* sort the table by this variable;
proc sort data=WITH_BINNS out=WITH_BINNS;
by &variable.;
run;
* Build start and end observation of particular bin;
data WITH_BINNS;
set WITH_BINNS;
by &rank_column.;
*this is just to check if first.&rank_column works;
first_&rank_column. = first.&rank_column.;
last_&rank_column. = last.&rank_column.;
%if first.&rank_column. = 1 %then %do;
/* here %if first.&rank_column. %then %do erros so something is wrong with argument statement*/
Start_bin = &variable.;
%end;
%else %do;
Start_bin = .;
%end;
%if last.&rank_column. = 1 %then %do;
End_bin = &variable.;
%end;
%else %do;
End_bin = .;
%end;
run;
%end;
* some more code which amends WITH_BINNS table;
%mend group_var_in_bins;
%group_var_in_bins(sashelp.cars);
结果如下:
因此循环无法识别 %if 部分中的参数。
感谢帮助!!
[编辑]:
澄清一下,我要执行的步骤是:
列表中的变量 &var_list。
为其建立排名
按该变量排序
逐步使用数据:按排名分组
找到这个变量的值,它对应于使用 first 的组的开始。并使用 last 结束组的结束。剩下的留空
一些后续步骤...
所以基本上我想创建排名间隔的乞讨和结束。
我以图片为例;第一行有第一个。 = 1 因此 Start_bin 应该是 $10.280 而 End_bin 应该是空的。下一行应该是空的,因为两者都在前。最后。是 0。
所以你的基本问题是你在应该使用普通逻辑的地方使用了宏逻辑。
%if first.&rank_column. = 1 %then %do;
永远不会为真,即使 rank_column
为空,因为字符串 first.
永远不会等于字符串 1
.
但是如果您使用 SAS 代码而不是宏代码对其进行编码
if first.&rank_column. = 1 then do;
那么,当您第一次观察到由宏变量 rank_column
.
您的整体逻辑可能存在更大的问题,因为您在同一数据集中覆盖了相同的变量名称 start_bin
和 end_bin
。因此只有您的列表的最后一个变量生成的 bin 的值在宏完成后才可用。
如果您最终要查找 bin 边界,groups=10,这是否等同于通过 proc summary 或 proc means 查找百分位数?通过百分位数方法进行操作的好处还意味着您可以一次处理多个变量。我没有在这里设置任何领带选项,但我相信也可以设置。
ods select none; /*do not display output - faster processing*/
proc means data=sashelp.cars /*input data set*/
stackods /*stack ods to have the table appear with statistics across the top*/
N NMISS Min P10 P20 P30 P40 P50 P60 P70 P80 P90 Max /*stats to show*/;
var mpg_city mpg_highway invoice msrp; /*variables included in analysis*/
ods output summary = want; /*capture output into a data set*/
run;
ods select all; /*reset output options*/