SAS Do Loops:如何使用在变量名称中包含迭代器的比较运算符?
SAS Do Loops: How do I use a comparison operator that includes the iterator in a variable name?
我有一个像 Cars1 这样的数据集(用下面的代码生成),变量名中有年份。
%macro test1();
data cars1;
set sashelp.cars (keep = make model);
%do i = 2012 %to 2014;
make&i. = make;
%end;
run;
%mend test1;
%test1();
看起来像这样...
Make Model make2012 make2013 make2014
Acura MDX Acura Acura Acura
Acura RSX Type S 2dr Acura Acura Acura
Acura TSX 4dr Acura Acura Acura
我想在 3 年 (2012-2014) 中进行迭代,根据与各自的比较,为我在 Cars1 中创建的 3 个变量中的每一个创建一个分类数据集(make_2012_cat,等等)价值。所以如果 make2012 eq 'Acura' 我有一个声明。与 make2021 ne 'Acura' 相同。出于某种原因,比较不起作用,我每次都以默认值结束(“它不可比较:-(”)
%macro test2();
data cars2;
set cars1;
%do i = 2012 %to 2014;
%if make&i. eq "Acura" %then %do;
make_&i._cat = "It's an Acura!";
%end;
%if make&i. ne "Acura" %then %do;
make_&i._cat = "It's not an Acura.";
%end;
%else %do;
make_&i._cat = "It's not comparable :-(";
%end;
%end;
run;
%mend test2;
%test2();
我最终只使用了默认值。我已经在宏的内部和外部尝试过这个,并且对我调用迭代器的方式进行了大量调整,我。也尝试过声明全局变量,但此时我只是在转动我的轮子。感谢任何帮助!!
Make make_2012_cat make_2013_cat make_2014_cat
Acura It's not an Acura. It's not an Acura. It's not an Acura.
Acura It's not an Acura. It's not an Acura. It's not an Acura.
Acura It's not an Acura. It's not an Acura. It's not an Acura.
因此,您需要了解宏语言和数据步骤语言之间的区别。这是两个不同的事情,实际上并不做同样的事情。
%if
和其他宏语言内容只会影响您正在编译的代码的文本。他们将 SAS 程序更改为其他一些 SAS 程序。但是他们没有任何东西可以处理数据!
步骤:
- 解析宏语言的东西
- 编译SAS数据步程序
- 运行 SAS数据步进程序(一次加载一行数据等)
因此需要将数据步骤(if
)与宏语言(%if
)分开。
%do i = 2012 %to 2014;
%if make&i. eq "Acura" %then %do;
make_&i._cat = "It's an Acura!";
%end;
%if make&i. ne "Acura" %then %do;
make_&i._cat = "It's not an Acura.";
%end;
%else %do;
make_&i._cat = "It's not comparable :-(";
%end;
%end;
把它变成
%do i = 2012 %to 2014;
if make&i. eq "Acura" then do;
make_&i._cat = "It's an Acura!";
end;
else if make&i. ne "Acura" then do; **note I added 'else' here;
make_&i._cat = "It's not an Acura.";
end;
else do;
make_&i._cat = "It's not comparable :-(";
end;
%end;
宏语言正在发挥它的作用 - 它正在创造
if make_2012_cat = ...;
if make_2013_cat = ...;
if make_2014_cat = ...;
但是数据步骤语言实际上是在做比较 make_2012_cat
变量值和 'Acura'
的工作。
注意另一件事;这不一定是非常惯用的 SAS。这是合法的,很多人都这样做,但它并没有真正最大限度地使用 SAS 功能。如果可以的话,最好是 make_cat
然后是 2012、2013、2014 的不同行。也许你不能 - 也许你有一个很好的理由 - 但是当你的变量名不包含数据(这些数据包含数据)时 更好 。也许你的真实例子是不同的,但我发现大约 80% 的时间当我看到人们大致这样做时,它可以在不同的数据结构中做得更好。
要完全在数据步骤中执行此操作,您需要数组。
data cars1;
set sashelp.cars (keep = make model);
array makes[3] make_2012-make_2014;
do _i = 1 to dim(makes);
makes[_i] = make;
end;
run;
data cars2;
set cars1;
array makes[3] make_2012-make_2014;
array makes_cat[3] make_cat_2012-make_cat_2014; *slightly different, easier;
do _i = 1 to dim(makes);
if makes[_i] eq "Acura" then makes_cat[_i] = "It's an Acura!";
else if makes[_i] ne "Acura" then makes_cat[_i] = "It's not an Acura.";
end;
run;
我有一个像 Cars1 这样的数据集(用下面的代码生成),变量名中有年份。
%macro test1();
data cars1;
set sashelp.cars (keep = make model);
%do i = 2012 %to 2014;
make&i. = make;
%end;
run;
%mend test1;
%test1();
看起来像这样...
Make Model make2012 make2013 make2014
Acura MDX Acura Acura Acura
Acura RSX Type S 2dr Acura Acura Acura
Acura TSX 4dr Acura Acura Acura
我想在 3 年 (2012-2014) 中进行迭代,根据与各自的比较,为我在 Cars1 中创建的 3 个变量中的每一个创建一个分类数据集(make_2012_cat,等等)价值。所以如果 make2012 eq 'Acura' 我有一个声明。与 make2021 ne 'Acura' 相同。出于某种原因,比较不起作用,我每次都以默认值结束(“它不可比较:-(”)
%macro test2();
data cars2;
set cars1;
%do i = 2012 %to 2014;
%if make&i. eq "Acura" %then %do;
make_&i._cat = "It's an Acura!";
%end;
%if make&i. ne "Acura" %then %do;
make_&i._cat = "It's not an Acura.";
%end;
%else %do;
make_&i._cat = "It's not comparable :-(";
%end;
%end;
run;
%mend test2;
%test2();
我最终只使用了默认值。我已经在宏的内部和外部尝试过这个,并且对我调用迭代器的方式进行了大量调整,我。也尝试过声明全局变量,但此时我只是在转动我的轮子。感谢任何帮助!!
Make make_2012_cat make_2013_cat make_2014_cat
Acura It's not an Acura. It's not an Acura. It's not an Acura.
Acura It's not an Acura. It's not an Acura. It's not an Acura.
Acura It's not an Acura. It's not an Acura. It's not an Acura.
因此,您需要了解宏语言和数据步骤语言之间的区别。这是两个不同的事情,实际上并不做同样的事情。
%if
和其他宏语言内容只会影响您正在编译的代码的文本。他们将 SAS 程序更改为其他一些 SAS 程序。但是他们没有任何东西可以处理数据!
步骤:
- 解析宏语言的东西
- 编译SAS数据步程序
- 运行 SAS数据步进程序(一次加载一行数据等)
因此需要将数据步骤(if
)与宏语言(%if
)分开。
%do i = 2012 %to 2014;
%if make&i. eq "Acura" %then %do;
make_&i._cat = "It's an Acura!";
%end;
%if make&i. ne "Acura" %then %do;
make_&i._cat = "It's not an Acura.";
%end;
%else %do;
make_&i._cat = "It's not comparable :-(";
%end;
%end;
把它变成
%do i = 2012 %to 2014;
if make&i. eq "Acura" then do;
make_&i._cat = "It's an Acura!";
end;
else if make&i. ne "Acura" then do; **note I added 'else' here;
make_&i._cat = "It's not an Acura.";
end;
else do;
make_&i._cat = "It's not comparable :-(";
end;
%end;
宏语言正在发挥它的作用 - 它正在创造
if make_2012_cat = ...;
if make_2013_cat = ...;
if make_2014_cat = ...;
但是数据步骤语言实际上是在做比较 make_2012_cat
变量值和 'Acura'
的工作。
注意另一件事;这不一定是非常惯用的 SAS。这是合法的,很多人都这样做,但它并没有真正最大限度地使用 SAS 功能。如果可以的话,最好是 make_cat
然后是 2012、2013、2014 的不同行。也许你不能 - 也许你有一个很好的理由 - 但是当你的变量名不包含数据(这些数据包含数据)时 更好 。也许你的真实例子是不同的,但我发现大约 80% 的时间当我看到人们大致这样做时,它可以在不同的数据结构中做得更好。
要完全在数据步骤中执行此操作,您需要数组。
data cars1;
set sashelp.cars (keep = make model);
array makes[3] make_2012-make_2014;
do _i = 1 to dim(makes);
makes[_i] = make;
end;
run;
data cars2;
set cars1;
array makes[3] make_2012-make_2014;
array makes_cat[3] make_cat_2012-make_cat_2014; *slightly different, easier;
do _i = 1 to dim(makes);
if makes[_i] eq "Acura" then makes_cat[_i] = "It's an Acura!";
else if makes[_i] ne "Acura" then makes_cat[_i] = "It's not an Acura.";
end;
run;