重命名变量,无论其在 SAS 中的名称如何

Rename Variable Regardless of its Name in SAS

假设我们有以下数据集:

ID    Stress_Level    Heart_Rate
1          5              10
2          7              12
3          9              16

用于重命名变量的代码是:

data test1;
    set test0;
    rename Stress_Level=A Heart_Rate=B;
run;

但是,我想做的是重命名 2 列而不使用它们的名称。是否有 "internal" SAS 命令根据变量所在的列来寻址变量?例如,第二列 Stress_Level 可以用 "COL2 " 或类似的名称来表示。因此代码将是:

data test1;
    set test0;
    rename COL2=A COL3=B;
run;

其中 "COL2" 将始终引用数据集中的第二列,而不管其名称如何。是否有直接或间接的方式来实现这一目标?

有几种方法可以做到这一点。


最短的方法可能是使用数组。唯一的缺点是你需要提前知道变量的类型和第一个变量的名称。

如果它们都是数字,如您的示例所示,则可以使用以下内容:

data test1;
    set test0;
    array vars[*] _numeric_;
    A = vars[2];
    B = vars[3];
    keep ID A B;
run;

数组中只能有一种类型的变量,所以如果它们不是全数字或全字符,它会稍微复杂一些。此外,如果您不想拥有第二个和第三个变量的副本,您还需要知道第一个变量的名称以及您希望保留的任何其他变量。


一种更可靠的方法是使用来自 dictionary table 的信息和一个宏变量来编写您的重命名语句:

proc sql;
    /* Write the individual rename assignments */
    select strip(name) || " = " || substr("ABCDEFGHIJKLMNOPQRSTUVWXYZ", varnum - 1, 1)
    /* Store them in a macro variable and separate them by spaces */
    into :vars separated by " "
    /* Use a sas dictionary table to find metadata about the dataset */
    from sashelp.vcolumn
    where 
        libname = "WORK" and 
        memname = "TEST0" and 
        2 <= varnum <= 3;
quit;
data test1;
    set test0;
    rename &vars.;
run;

SAS 将有关数据集的信息存储在字典 table 中,这些信息在 sashelp 库中具有可用的视图。查看一些 sashelp.v* table 以查看可用的信息类型。 proc sql colon 用于将值存储在宏变量中,然后可以在 rename 语句中使用。


我推荐第二种方法,因为它更加灵活,而且对数据的确切结构的依赖性更低。当您有多个变量要重命名时,它也可以更好地扩展。

最后,如果您想就地更改数据集,您可能想看看使用 proc datasets(结合字典 table 方法)进行重命名,因为这可以更改变量名称,而无需读取和写入每一行数据。

我认为最简单的方法是从元数据 table DICTIONARY.COLUMNS 中构建一个重命名语句字符串(对此的看法是 SASHELP.VCOLUMN)。这包含活动库中所有 table 的列名和位置。
我利用 ASCII 序列(byte 函数)重命名列 A、B 等,显然如果要重命名的列超过 26 个,你 运行 就会遇到问题table! 如果您想从与 2 不同的列开始,您还需要调整 varnum+63 计算。

proc sql noprint;
select cats(name,"=",byte(varnum+63)) into :newvars separated by ' '
from dictionary.columns
where libname = 'WORK' and memname='HAVE' and varnum>=2;
quit;

data want;
set have;
rename &newvars.;
run;

/* or */

/*
proc datasets lib=work nolist nodetails;
modify have;
rename &newvars.;
quit;
*/