Hey.
Let's consider the table 'Cars' and table 'Dictionary'.
Table dictionary has two variables, first: ID of a row, second: condition which determines what ID has a particular row.
For instance, where a record:
Type='SUV' and Horsepower > 300 and Cylinders > 6 THEN ID=TYPE_A
Now, using var_condition and var_id I would like to flag every record of a dataset by an 'ID' and stack them in a new table. I tried simple macro %if &var_condition then new_column = &ID, but I am not even close. How can I approach this task?
data cars;
set sashelp.cars;
run;
data Dictionary;
input ID : $6. Condition & $211.;
datalines;
TYPE_A upcase(Type) IN('SUV', 'SPORTS', 'WAGON') and upcase(Origin) = 'ASIA' AND Horsepower > 150
TYPE_B Horsepower >= 220 and upcase(Origin)='EUROPE'
TYPE_C Type='SUV' and Horsepower > 300 and Cylinders > 6
;
proc sql noprint;
select ID into :var_id seprated by ' '
from Dictionary;
proc sql noprint;
select Condition into :var_condition seprated by ' '
from Dictionary;
You definitely don't want to generate a macro %IF statement if you want to apply the condition to actual data.
Step 1 is to write the SAS code you want to generate.
data want;
set cars;
length id $6 ;
if upcase(Type) IN('SUV', 'SPORTS', 'WAGON') and upcase(Origin) = 'ASIA'
AND Horsepower > 150 then id="TYPE_A";
else if Horsepower >= 220 and upcase(Origin)='EUROPE' then id="TYPE_B ";
else if Type='SUV' and Horsepower > 300 and Cylinders > 6 then id="TYPE_C";
run;
Once you get that working then you can try to figure out how to generate it from the data you have.
filename code temp;
data _null_;
set dictionary;
file code;
if _n_ > 1 then put ' else' @ ;
put ' if ' condition 'then id=' id :$quote. ';' ;
run;
data want;
set cards;
length id $6;
%include code / source2;
run;
Updated: to remove spurious SEP variable reference in PUT statement.
Did you read your log?
Dictionary is a special word for proc sql and when you do not specify the library that such as with WORK.Dictionary then proc sql expects a name of one of the dictionary tables that SAS maintains such as Dictionary.Tables, Dictionary.columns or others.
So a a minimum you need code similar to:
proc sql noprint; select ID into :var_id separated by ' ' from work.Dictionary; quit; proc sql noprint; select Condition into :var_condition separated by ' ' from Work.Dictionary; quit;
Note correction in "separated" as well.
You don't show anything about how you actually attempted to use the macro variables.
Since %IF would be applied in the compile phase of a data step it is very likely that you compared something not available to the data step.
I'm guessing you are wanting to use the types (ID) to pass into some sort of where clause where the condition is then applied. If I'm guessing right, then you'd take your dataset with your ID & condition text, then use data _null_ with call symputx to create macro variables for each type, that would hold the conditional text string. Then you use the macro variable to refer to the condition in later where statements or SQL clauses. Is this what you're trying to do?
data cars;
set sashelp.cars;
run;
data Dictionary;
input ID : $6. Condition & $211.;
datalines;
TYPE_A upcase(Type) IN('SUV', 'SPORTS', 'WAGON') and upcase(Origin) = 'ASIA' AND Horsepower > 150
TYPE_B Horsepower >= 220 and upcase(Origin)='EUROPE'
TYPE_C Type='SUV' and Horsepower > 300 and Cylinders > 6
;
data _null_;
set dictionary;
call symputx(id,condition);
run;
data want;
set sashelp.cars;
where &TYPE_A.;
run;
You definitely don't want to generate a macro %IF statement if you want to apply the condition to actual data.
Step 1 is to write the SAS code you want to generate.
data want;
set cars;
length id $6 ;
if upcase(Type) IN('SUV', 'SPORTS', 'WAGON') and upcase(Origin) = 'ASIA'
AND Horsepower > 150 then id="TYPE_A";
else if Horsepower >= 220 and upcase(Origin)='EUROPE' then id="TYPE_B ";
else if Type='SUV' and Horsepower > 300 and Cylinders > 6 then id="TYPE_C";
run;
Once you get that working then you can try to figure out how to generate it from the data you have.
filename code temp;
data _null_;
set dictionary;
file code;
if _n_ > 1 then put ' else' @ ;
put ' if ' condition 'then id=' id :$quote. ';' ;
run;
data want;
set cards;
length id $6;
%include code / source2;
run;
Updated: to remove spurious SEP variable reference in PUT statement.
Hey, thank your for your replay.
Does this code compiles without an error for you?
data cars;
set sashelp.cars;
run;
data dictionary;
input ID : $6. Condition & $211.;
datalines;
TYPE_A upcase(Type) IN('SUV', 'SPORTS', 'WAGON') and upcase(Origin) = 'ASIA' AND Horsepower > 150
TYPE_B Horsepower >= 220 and upcase(Origin)='EUROPE'
TYPE_C Type='SUV' and Horsepower > 300 and Cylinders > 6
;
filename code temp;
data _null_;
set dictionary;
file code;
if _n_ > 1 then put 'else' @ ;
put sep ' if ' condition 'then id=' id :$quote. ';' ;
run;
data want;
set cars;
length id $6;
%include code / source2;
run;
I am ha
What should "sep" do in this statement?
put sep ' if ' condition 'then id=' id :$quote. ';' ;
Your code seems to work well without it.
The SEP should be removed. It was left over from a different coding pattern for how to handle the conditional generation of the ELSE keyword.
Maxim 18: Separate Your Names.
"Dictionary" is a "keyword" in SQL and should therefore not be used for names of objects (datasets, variables).
Which of your conditions should take precedence if an observation meets more than one condition (e.g. an SUV from Asia or Europe with 8 cylinders and 350 horsepower)?
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.