【问题标题】:dropping variables using a macro variable containing list of varnames使用包含 varnames 列表的宏变量删除变量
【发布时间】:2023-03-19 02:32:01
【问题描述】:

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

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

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

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

data _null_;

length allvars $1000;

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) 然后我尝试使用以下代码从我的 inputds 中删除它,我收到一条警告消息并且没有发生删除:

    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;

【问题讨论】:

    标签: sas sas-macro


    【解决方案1】:

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

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

    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 个字符时,其中一个变量名称被截断。分配更多空间会有所帮助。

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

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

    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

    【讨论】:

    • 感谢系统的回复。 to_drop 包含一个名为 TYPE 的变量,它不在 inputds 中。但是,创建常用名称列表的 SQL 代码不起作用 - 返回一个包含 0 个观察值的表。我认为问题出在 b.name 上,因为在 inputds 中,变量名是实际的变量名。
    • 如果我可以从 to_drop 中删除类型,我可能会回家
    • 我只记得dictionary.columns 中的memname 变量是全大写的。所以你需要b.memname = 'INPUTDS'。编辑了我的答案。请再次尝试 SQL 位,看看它是否适合您。
    • "请注意,DICTIONARY 表中的许多字符值都存储为全大写字符;您应该相应地设计查询。"那是来自support.sas.com/documentation/cdl/en/lrcon/62955/HTML/default/…
    • @vagabond:加入upcase(a._name_) = upcase(b.name) 可能是个好主意,以避免因大写导致变量名不匹配。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-12
    • 1970-01-01
    • 2023-03-11
    • 1970-01-01
    • 2011-09-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多