微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

SAS Do Loops:如何使用在变量名称中包含迭代器的比较运算符?

如何解决SAS Do Loops:如何使用在变量名称中包含迭代器的比较运算符?

我有一个像 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 程序。但他们与数据没有任何关系

步骤:

  1. 解析宏语言内容
  2. 编译SAS数据步程序
  3. 运行 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;

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。