如何删除SAS中仅声明为“ Null”但不为空的多个列变量?我已经创建了下表;
DATA test;
INPUT name$ favourite_food$ occupation$ favourite_sport$;
CARDS;
John Null Nurse Null
Michelle Null Lawyer Null
Peter Null Teacher Null
Kai Null Doctor Null
run;
由于具有Null值的列不是空白,所以我不确定如何删除这些列。我不需要它们进行分析。
我也知道我可以使用drop命令删除列。但是,当我有大约90个变量时,还有一种更有效的方法来删除多个“空”变量
答案 0 :(得分:3)
nlevels
中的proc freq
选项返回每列中不同值的数量。因此,所有值都相同的列的nlevel值将为1。
如果您确信此规则仅适用于“空”列,则可以使用此方法(即,至少有2个不同的名称,职业等值)。
nlevel
的值不会自动包含在proc freq
中的输出表中,因此您需要使用ods output
将列名放入表中。然后,您可以将它们分配给宏变量,以便在所使用的任何分析过程中的drop
语句中使用。或者,您可以按照数据步骤中的要求将其删除。 (我通常更喜欢前一种选择,以防万一错误删除了有效数据)。
DATA test;
INPUT name$ favourite_food$ occupation$ favourite_sport$;
CARDS;
John Null Nurse Null
Michelle Null Lawyer Null
Peter Null Teacher Null
Kai Null Doctor Null
run;
/* identify columns with only 1 distinct value and output to a table */
ods output nlevels = distinct_values (where=(nlevels=1));
proc freq data=test nlevels;
run;
/* store column names in macro variable */
proc sql noprint;
select tablevar into :drop_cols separated by ' '
from distinct_values;
quit;
%put &drop_cols;
/* exclude columns from analysis */
proc freq data=test (drop=&drop_cols.);
run;
答案 1 :(得分:1)
需要对数据进行全面扫描,以检查所有列中的所有值。在扫描期间,如果出现"Null"
以外的值,则该列将不作为删除候选对象。
您可以使用一个临时数组来跟踪字符列名称是什么,并将另一个数组设置为_CHARACTER_
,以便可以在每一行中迭代这些列。该过程将构建可以根据您的条件删除的列的列表-该列表位于宏符号表中,并且可以在后续代码中使用,以重写不包含这些列的数据,或者只是删除在处理过程中使用数据集选项。
DATA test;
INPUT name$ favourite_food$ occupation$ favourite_sport$;
CARDS;
John Null Nurse Null
Michelle Null Lawyer Null
Peter Null Teacher Null
Kai Null Doctor Null
Zonker Null Null Null
run;
%let DROP_VARS=;
data _null_;
set test end=end;
array char_vars _CHARACTER_; * for iterating over values;
array null_vars (1000) $32 _temporary_ ; * for tracking column names;
* populate column name tracking array;
if _n_ = 1 then do;
do index = 1 to dim(char_vars);
null_vars(index) = vname(char_vars(index));
end;
end;
* scan each row, iterating over character variables;
* remove a column name from drop consideration when non "Null" occurs;
do index = 1 to dim(char_vars);
if not missing(null_vars(index)) then
if char_vars(index) ne "Null" then
null_vars(index) = '';
end;
* place space separated list of columns containing only "Null" in macro symbol table;
if end then
call symput('DROP_VARS', catx(' ', of null_vars(*)));
run;
* use macro variable as desired;
%put NOTE: &=DROP_VARS;
proc print data=test(drop=&DROP_VARS);
title "Non-null columns of TEST";
run;
data TEST2(label="Copy of Test, excluding null columns");
set TEST;
drop &DROP_VARS;
run;
还有许多其他SAS方式来为删除具有相同值的列编码解决方案–向上搜索它们!
答案 2 :(得分:1)
在这种情况下,您有两种选择。
1,使用保持。 keep函数保留您想要的变量,因此,如果您已经知道变量不是NULL的话,只需放入keep,例如:
数据测试(保持=最喜欢的食物职业);
INPUT name$ favourite_food$ occupation$ favourite_sport$;
CARDS;
John Null Nurse Null
Michelle Null Lawyer Null
Peter Null Teacher Null
Kai Null Doctor Null
运行;
如果您知道favorite_food并且职业不是NULL。
2,使用删除功能示例:
数据测试;
INPUT name$ favourite_food$ occupation$ favourite_sport$;
CARDS;
if name eq NULL then delete;
运行;
祝你好运!
答案 3 :(得分:0)
在宏中使用sql的另一种方法。添加详细注释。 @longfish解决方案简单有效。
%macro abc;
/* picking up the variables on which Null check is needed*/
proc sql;
/*finding total number of obervations*/
select count(*) into :cnt from test;
select name into :name separated by '|' from dictionary.columns
where upcase(memname) = 'TEST'
and lowcase(name) like '%favourite_%';
/*creting temporary table to hold the values which should be dropped*/
create table temptable(col char(50),val num);;
/* looping through variables for which null check is needed*/
%do i = 1 %to %sysfunc(countw(&name, |));
%let col_val =%scan(&name,&i,|);
/* total obervations minus count for variables with null values gives 0
indicates that all are null values and are inseted in a temptable*/
proc sql;
insert into temptable
select col, val from
(select "&col_val" as col , &cnt- count(&col_val) as val
from test
where &col_val = "Null")
where val = 0;
%end;
/*picking up all the columns to be dropped*/
proc sql;
select col into :drop_columns separated by ' '
from temptable;
%put &drop_columns;
/* dropping the columns*/
data want;
set test(drop=&drop_columns);
run;
%mend;
%abc;