使用包含变量名列表的宏变量删除变量
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
。
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
。