【问题标题】:SAS - Creating variables from macro variablesSAS - 从宏变量创建变量
【发布时间】:2013-03-17 17:13:22
【问题描述】:

我有一个 SAS 数据集,其中包含 20 个字符变量,所有这些都是名称(例如 Adam、Bob、Cathy 等)

我想要一个动态代码来创建名为 Adam_ref、Bob_ref 等的变量。即使存在具有不同名称的不同数据集(即不想手动定义每个变量),它也可以工作。

到目前为止,我的方法是使用 proc 内容获取所有变量名称,然后使用宏创建宏变量 Adam_ref、Bob_ref 等。

如何从这里在数据集中创建实际变量?我需要不同的方法吗?

proc contents data=work.names 
               out=contents noprint;
run;

proc sort data = contents; by varnum; run;

data contents1;
  set contents;
  Name_Ref = compress(Name||"_Ref");
  call symput (NAME, NAME_Ref); 
  %put _user_;
run;

【问题讨论】:

    标签: sas sas-macro


    【解决方案1】:

    如果您想创建一个空数据集,其中的变量命名类似于宏变量中的某些值,您可以执行以下操作。

    将值保存到以某种模式命名的宏变量中,例如v1v2 ...

    proc sql;
    select compress(Name||"_Ref") into :v1-:v20 from contents;
    quit;
    

    如果你不知道有多少个值,你必须先数一数,我假设只有 20 个。

    然后,如果你所有的变量都是长度为 100 的字符变量,你创建一个这样的数据集:

    %macro create_dataset;
    data want;
    length %do i=1 %to 20; &&v&i $100 %end;
    ;
    stop;
    run;
    %mend;
    
    %create_dataset; run; 
    

    如果你有宏变量中的值,你可以这样做,一般来说可能有更好的方法。

    如果您不想创建空数据集而只想更改变量名称,您可以这样做:

    proc sql;
    select name into :v1-:v20 from contents;
    quit;
    
    %macro rename_dataset;
    data new_names;
    set have(rename=(%do i=1 %to 20; &&v&i = &&v&i.._ref %end;));
    run;
    %mend;
    
    %rename_dataset; run;
    

    【讨论】:

    • 您不必计算变量的数量,PROC SQL 会为您计算到 SQLOBS 自动宏变量中。 %let n=&sqlobs; %do i=1 %to &n; ... 加上较新版本的 SAS,您可以省略 INTO 子句的上限:into :v1-。对于旧版本的 SAS,您可以为上限设置一个非常大的数字 into :v1-:v99999,SQL 只会为查询返回的观察数创建足够的宏变量。
    【解决方案2】:

    您可以将 PROC TRANSPOSE 与 ID 语句一起使用。

    此步骤创建一个示例数据集:

    data names;
        harry="sally";
        dick="gordon";
        joe="schmoe";
    run;
    

    此步骤本质上是您上述步骤的副本,它会生成列名数据集。我将在整个过程中重复使用数据集名称引用。

    proc contents data=names out=namerefs noprint;
    run;
    

    此步骤将“_Refs”添加到之前定义的名称中,并删除其他所有内容。变量“name”来自PROC CONTENTS输出的数据集的列属性。

    data namerefs;
        set namerefs (keep=name);
        name=compress(name||"_Ref");
    run;
    

    此步骤会生成一个包含所需列的空数据集。通过查看列属性再次获得变量“name”。如果您尝试查看数据集,您可能会在 GUI 中收到无害的警告,但您可以根据需要使用它,并且可以确认它具有所需的输出。

    proc transpose out=namerefs(drop=_name_) data=namerefs;
      id name;
    run;
    

    【讨论】:

      【解决方案3】:

      这是另一种需要较少编码的方法。它不需要运行 proc 内容,不需要知道变量的数量,也不需要创建宏函数。它也可以扩展来做一些额外的事情。

      第 1 步是使用内置的字典视图来获取所需的变量名称。合适的视图是 dictionary.columns,它的别名是 sashelp.vcolumn。字典 libref 只能在 proc sql 中使用,而 sashelp 别名可以在任何地方使用。我倾向于使用 sashelp 别名,因为我使用 DMS 在 Windows 中工作,并且始终可以交互地查看 sashelp 库。

      proc sql;
        select compress(Name||"_Ref") into :name_list
                                      separated by ' '
          from sashelp.vcolumn
         where libname = 'WORK' 
           and memname = 'NAMES';
      quit;
      

      这会生成一个带有所需名称的空格分隔宏。

      第 2 步要构建空数据集,则此代码将起作用:

      Data New ;
        length &name_list ;
      run ;
      

      您可以避免假设长度或使用稍微复杂的选择语句创建具有新变量名称的填充数据集。

      例如

       select compress(Name)||"_Ref $")||compress(put(length,best.)) 
                       into :name_list
                       separated by ' '
      

      将生成一个宏变量,该变量保留每个变量的先前长度。这将在不更改上述步骤 2 的情况下工作。

      要创建用于重命名数据集选项的填充数据集,请将 select 语句替换如下:

       select compress(Name)||"= "||compress(_Ref") 
                         into :name_list
                         separated by ' '
      

      然后将步骤 2 代码替换为以下内容:

      Data New ;
        set names (rename = ( &name_list)) ;
      run ;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-23
        • 1970-01-01
        • 2017-10-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多