Hello
I want to delete (DROP) columns if they exist.
For example: I want to drop columns make and model if they exist.
data cars;
set sashelp.cars;
drop make;
Run;
If you set system option drkrocond=nowarn, you can list the variables that don't exist on the DROP statement, and they will be ignored.
1 option dkrocond=nowarn ; 2 3 data cars ; 4 set sashelp.cars ; 5 drop make notthere; 6 run ; NOTE: There were 428 observations read from the data set SASHELP.CARS. NOTE: The data set WORK.CARS has 428 observations and 14 variables. 7 8 option dkrocond=warn
Do you want to remove the column from an existing dataset or do you want to clone a dataset skipping one variable?
Query DICTIONARY.COLUMNS with a suitable WHERE clause in a SELECT INTO to create the variable list which you can then use in a DROP statement or DROP= dataset option.
Here is a macro example that allows you to check if a variable exists in a data set:
https://support.sas.com/kb/25/082.html
If the variable does not exist, the value of &val is 0. Otherwise, the value is the variable's position in the data set.
If you set system option drkrocond=nowarn, you can list the variables that don't exist on the DROP statement, and they will be ignored.
1 option dkrocond=nowarn ; 2 3 data cars ; 4 set sashelp.cars ; 5 drop make notthere; 6 run ; NOTE: There were 428 observations read from the data set SASHELP.CARS. NOTE: The data set WORK.CARS has 428 observations and 14 variables. 7 8 option dkrocond=warn
macro version, no need for options change in main session thanks to DoSubL() 🙂
%macro dropVariableIfExistQ(
ds /* name of data set with variables to drop */
, vars /* space separated list of variables to drop */
, out=work.want /* name of result data set */
);
%local rc;
%let rc = %sysfunc(doSubL(%str(
options nomprint nosymbolgen nomlogic msglevel=N nosource ps=min notes;
option dkrocond=nowarn;
data &out.;
set &ds.;
drop
&vars.
;
run;
)));
%mend dropVariableIfExistQ;
options mprint;
%dropVariableIfExistQ(sashelp.cars, make model)
%put ##%dropVariableIfExistQ(sashelp.cars, NOmake NOmodel, out=work.want2)##;
Bart
@Quentin , expanding your idea a little bit:
%macro bpUTiL_cleanDropKeep(
/* idea by Quentin McMullen */
ds /* name of data set with variables to drop */
, drop= /* space separated list of variables to drop */
, keep= /* space separated list of variables to keep */
, out=work.want /* name of result data set */
);
%local rc;
%put NOTE-;
%let rc = %sysfunc(doSubL(%nrstr(
options nomprint nosymbolgen nomlogic msglevel=N nosource ps=min notes;
option dkrocond=nowarn;
data &out.;
set &ds.;
%sysfunc(ifc(%sysevalf(%superq(drop) NE ,boolean)=1, %str(drop &drop.), %str( ), ));
%sysfunc(ifc(%sysevalf(%superq(keep) NE ,boolean)=1, %str(keep &keep.), %str( ), ));
run;
)));
%put NOTE-;
%mend bpUTiL_cleanDropKeep;
options mprint;
%bpUTiL_cleanDropKeep(sashelp.cars, drop=make model)
%put ##%bpUTiL_cleanDropKeep(sashelp.cars, keep=NOmake NOmodel, out=work.want2)##;
I think I'll add it to bpUTiL package 🙂
[EDIT:] I've added Rename to have it all:
%macro bpUTiL_cleanDropKeep(
/* idea by Quentin McMullen */
ds /* name of data set with variables to drop */
, drop= /* space separated list of variables to drop */
, keep= /* space separated list of variables to keep */
, rename= /* list of variables pairs to rename */
, out=work.want /* name of result data set */
);
%local rc;
%put NOTE-;
%let rc = %sysfunc(doSubL(%nrstr(
options nomprint nosymbolgen nomlogic msglevel=N nosource ps=min notes;
option dkrocond=nowarn;
data &out.;
set &ds.;
%sysfunc(ifc(%sysevalf(%superq(drop) NE ,boolean)=1, %str(drop &drop.), , ));
%sysfunc(ifc(%sysevalf(%superq(keep) NE ,boolean)=1, %str(keep &keep.), , ));
%sysfunc(ifc(%sysevalf(%superq(rename) NE ,boolean)=1, %str(rename &rename.), , ));
run;
)));
%put NOTE-;
%mend bpUTiL_cleanDropKeep;
options mprint;
%bpUTiL_cleanDropKeep(sashelp.cars, drop=make model)
%put ##%bpUTiL_cleanDropKeep(sashelp.cars, keep=NOmake NOmodel, out=work.want2)##;
%bpUTiL_cleanDropKip(sashelp.cars,keep=make ABC, rename=ABC=EFG make=make_make_make)
Bart
Nice, @yabwon .
I actually picked up the idea of using DKROCOND that way from SAS guru Ed Heaton, who wrote about it here:
https://support.sas.com/resources/papers/proceedings/proceedings/sugi28/067-28.pdf
As mentioned in the paper, he was a fan of putting drop=_: in every DATA step he wrote.
Small macro, just for fun;
%macro dropVariableIfExist(
ds /* name of data set with variables to drop */
, vars /* space separated list of variables to drop */
, out=work.want /* name of result data set */
);
%local sentinel rc;
%let sentinel=_sentinel_%sysfunc(datetime(),b8601dt15.)_;
%let rc = %sysfunc(doSubL(%str(
options nomprint nosymbolgen nomlogic msglevel=N nosource ps=min nonotes;
data _null_;
&sentinel._1_=.;
if 0 then set &ds.;
&sentinel._2_=" ";
array _numeric_(&sentinel._I_) _numeric_;
array _character_(&sentinel._I_) _character_;
length &sentinel._3_ $ 32767;
&sentinel._3_=" ";
length &sentinel._K_ $ 32;
&sentinel._K_ = "*";
declare hash &sentinel._H_();
&sentinel._H_.defineKey("&sentinel._K_");
&sentinel._H_.defineDone();
do _N_ = 1 by 1 while(&sentinel._K_ NE " ");
&sentinel._K_ = upcase(scan(symget("vars"),_N_," "));
&sentinel._H_.REPLACE(KEY:&sentinel._K_
,DATA:&sentinel._K_
);
end;
do over _numeric_;
if 0=&sentinel._H_.CHECK(KEY:upcase(strip(vname(_numeric_)))) then
&sentinel._3_=catX(" ", &sentinel._3_, vname(_numeric_));
end;
do over _character_;
if 0=&sentinel._H_.CHECK(KEY:upcase(strip(vname(_character_)))) then
&sentinel._3_=catX(" ", &sentinel._3_, vname(_character_));
end;
if &sentinel._3_ NE " " then
do;
put "INFO: The following variables: " &sentinel._3_ "will be dropped.";
call execute("options notes source; data " !! symget("out") !! ";");
call execute(" set " !! symget("ds") !! ";");
call execute(" drop ");
call execute(&sentinel._3_);
call execute("; run;");
end;
else put "INFO: No variables to drop.";
/* put _ALL_; */
stop;
run;
)));
%mend dropVariableIfExist;
options mprint;
%dropVariableIfExist(sashelp.cars, make model)
%put ##%dropVariableIfExist(sashelp.cars, NOmake NOmodel, out=work.want2)##;
It runs as pure macrocode 🙂
Bart
April 27 – 30 | Gaylord Texan | Grapevine, Texas
Walk in ready to learn. Walk out ready to deliver. This is the data and AI conference you can't afford to miss.
Register now and lock in 2025 pricing—just $495!
Still thinking about your presentation idea? The submission deadline has been extended to Friday, Nov. 14, at 11:59 p.m. ET.
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.
Ready to level-up your skills? Choose your own adventure.