使用包含变量名列表的宏变量删除变量

dropping variables using a macro variable containing list of varnames

SAS 的初学者。我想从我的输入中删除一个变量列表。该列表本身作为观察结果出现在另一个数据集中。在谷歌搜索后,我发现了这篇关于该主题的优秀论文。

http://www2.sas.com/proceedings/sugi30/028-30.pdf

所以我使用下面的代码在宏变量中创建了一个列表:

/*make a list of variables as a macro variable */

data _null_;

length allvars 00;

retain allvars ' ';

set to_drop end=eof;

allvars = trim(left(allvars))||' '||left(_name_);

if eof then call symput('varlist', allvars);

run;

我现在面临三个问题:

1) 当我 %PUT &VARLIST 时,日志只显示 31 个变量,而我的列表实际上是 2000 多个变量。

2) 我不太明白语句:trim(left(allvars)) || ' ' || left(_name_); 是做什么的。我知道 trim 删除前导空格,left 是对齐左字符串,但无法理解完整的语句。

3) 然后我尝试使用以下代码从我的输入中删除它,我收到一条警告消息并且没有发生删除:

    data inputds2 (drop = &varlist);
    set inputds;
    run;



WARNING: The variable avg_weighted in the DROP, KEEP, or RENAME list has never been referenced.

NOTE: There were 43662 observations read from the data set WORK.INPUTDS.

NOTE: The data set WORK.INPUTDS2 has 43662 observations and 3465 variables.

实际上我的变量名是这样写的:avg_weighted_minutes_view_3739 avg_weighted_minutes_view_7963 avg_weighted_minutes_view_(XXXX) 最后 4 位数字是随机的。这些是 SAS 生成的名称,因为我的标签包含空格。

编辑:尝试使用另一个部分工作的代码 - 它制作了一个更大的列表 - &VARLIST 宏变量中 2000 多个变量中的大约 1000 个。

data _null_;

set to_drop;

call symput('varlist',trim(

resolve('&varlist')

)||' '||trim(_name_));

run;

%put &varlist;

我会按照提供的顺序回答。

1.) 如果要删除 2,000 多个变量,则 1,000 个字符不足以容纳变量名称列表,因此列表将被截断。您需要在空数据步骤中为 allvars 变量分配更多 space,如下所示:

data _null_;
    length allvars $ 10000; /* You may need even more! */
    retain allvars;
    set to_drop end=eof;
    allvars = trim(left(allvars)) || ' ' || left(_name_);
    if eof then call symput('varlist', allvars);
run;

您可能会收到您记下的日志消息,因为当列表的长度达到 1,000 个字符时,其中一个变量名被截断了。分配更多 space 会有所帮助。

2.) trim() 函数从字符串中删除尾随空格。 left() 左对齐字符串中的字符值,因此任何前导空格都被推到后面。 || 是 SAS 中的字符串连接运算符。所以完整的声明是这样做的:

  • 从列表中删除白色space,以便 " x y " 变为 "x y"
  • 在末尾添加一个空格来分隔变量名,因此 "x y" 变为 "x y "
  • 将下一个变量名称添加到字符串中,例如"x y " 变为 "x y z"。最后一个变量名是左对齐的,因此变量名之间只有一个 space。

3.) 您收到该日志消息是因为数据集 to_drop 中有一个变量在输入数据集中不存在(如果 to_drop 是创建为 PROC CONTENTS 或类似的输出),或者如我提到的那样列表被截断了。为避免 to_drop 未从 PROC CONTENTS 输出的问题,您可以过滤掉不在输入数据集中的变量,如下所示:

proc sql;
    create table to_drop2 as
    select distinct a._name_
    from to_drop as a
    inner join dictionary.columns as b
    on a._name_ = b.name
    where b.memname = 'INPUTDS';
quit;

但如果问题是名称被截断,分配更多长度将解决这个问题。


也许更好的方法是使用 PROC SQL 一步完成所有操作。这将确保宏变量 varlist 达到所需的长度,达到最大允许长度。

proc sql noprint;
    select distinct a._name_
    into :varlist
    separated by ' '
    from to_drop as a
    inner join dictionary.columns as b
    on a._name_ = b.name
    where b.memname = 'INPUTDS';
quit;

请注意,如果 to_drop 仅包含 inputds 中的变量,则无需加入 dictionary.columns