I am trying to decide whether a car type has Hybrid cars or not and will write that out in a footnote when creating a report.
%let make=Honda;
data &make(keep=Make Model Type MSRP HybridFlag);
set sashelp.cars end=lastrow; * is used in the SET statement to create a temporary variable named LastRow. LastRow is initialized to 0 and will be set to 1 when the last row is read from the input table. It serves as an end-of-file indicator.;
where upcase(Make)="%upcase(&make)";
retain HybridFlag;
if Type="Hybrid" then HybridFlag=1;
if lastrow then do; * *********************** These are empty do loops;
if HybridFlag=1 then do;
%let foot=&make Offers Hybrid Cars;
end;
else do;
%let foot=&make Does Not Have a Hybrid Car;
end;
end;
run;
title "&make Cars";
footnote "&foot";
proc print data=&make noobs;
var Model Type MSRP HybridFlag;
run;
title;footnote;
So the answer in the report is that Honda does not have a Hybrid car despite that it obviously has.
In the second row of the code I tried:
set sashelp.cars(obs=2) end=lastrow;
to only include Hybrid cars (I did this since I got out of ideas and simply needed to "play" with the code). This produced the wrong footnote again.
I have no clue why this error occurs.
The output table from the proc print statement:
Model | Type | HybridFlag |
Civic Hybrid 4dr manual (gas/electric) | Hybrid | 1 |
Insight 2dr (gas/electric) | Hybrid | 1 |
Pilot LX | SUV | 1 |
CR-V LX | SUV | 1 |
Element LX | SUV | 1 |
Civic DX 2dr | Sedan | 1 |
Civic HX 2dr | Sedan | 1 |
Civic LX 4dr | Sedan | 1 |
Accord LX 2dr | Sedan | 1 |
Accord EX 2dr | Sedan | 1 |
Civic EX 4dr | Sedan | 1 |
Civic Si 2dr hatch | Sedan | 1 |
Accord LX V6 4dr | Sedan | 1 |
Accord EX V6 2dr | Sedan | 1 |
Odyssey LX | Sedan | 1 |
Odyssey EX | Sedan | 1 |
S2000 convertible 2dr | Sports | 1 |
Honda Does Not Have a Hybrid Car
My question:
1. Why does the error occur (The footnote is that Honda does not have a Hybrid car despite that it obviously has) ?
2. I know that the problem can be handled by the function: symputx but my understanding of it is limited since I don't understand question 1 from the first place.
Thanks.
%LET statements are not part of the data step code, and will not be executed conditionally in an IF statement.
Instead, use CALL SYMPUT or CALL SYMPUTX:
%let make=Honda;
data &make(keep=Make Model Type MSRP HybridFlag);
set sashelp.cars end=lastrow; * is used in the SET statement to create a temporary variable named LastRow. LastRow is initialized to 0 and will be set to 1 when the last row is read from the input table. It serves as an end-of-file indicator.;
where upcase(Make)="%upcase(&make)";
retain HybridFlag;
if Type="Hybrid" then HybridFlag=1;
if lastrow then do; * *********************** These are NOT empty do loops;
if HybridFlag=1 then do;
call symputx('foot',"&make Offers Hybrid Cars");
end;
else do;
call symputx('foot',"&make Does Not Have a Hybrid Car");
end;
end;
run;
title "&make Cars";
footnote "&foot";
proc print data=&make noobs;
var Model Type MSRP HybridFlag;
run;
title;footnote;
With you original construct, both %LET statements were executed (before execution of the data step), and the last one was the one that had effect.
If you do not want the flag variable, you can simplify your code like this:
%let make=Honda;
%let foot=&make Does Not Have a Hybrid Car;
data &make(keep=Make Model Type MSRP);
set sashelp.cars;
where upcase(Make)="%upcase(&make)";
if Type="Hybrid" then
call symputx('foot',"&make Offers Hybrid Cars");
run;
title "&make Cars";
footnote "&foot";
proc print data=&make noobs;
var Model Type MSRP;
run;
title;footnote;
The key to writing macros that work is to write SAS code that works for one instance (in this case, Honda) that does not have macros and does not have macro variables. Once you get that to work properly, then you should be able to turn it into a macro relatively easily. If you don't have working code without macros, then it is unlikely that your macro will work. In this case, you have obviously not done this step, because your code does not produce the desired results. So you need to do this step.
To debug existing macros, you should use the command
options mprint;
as the first line of your program, then re-run the program and look at the LOG. If looking at the log doesn't help you debug, then show us the log, by copying it as text and pasting it into the window that appears when you click on the </> icon. DO NOT POST THE LOG WITHOUT CLICKING ON THE </> ICON.
%LET statements are not part of the data step code, and will not be executed conditionally in an IF statement.
Instead, use CALL SYMPUT or CALL SYMPUTX:
%let make=Honda;
data &make(keep=Make Model Type MSRP HybridFlag);
set sashelp.cars end=lastrow; * is used in the SET statement to create a temporary variable named LastRow. LastRow is initialized to 0 and will be set to 1 when the last row is read from the input table. It serves as an end-of-file indicator.;
where upcase(Make)="%upcase(&make)";
retain HybridFlag;
if Type="Hybrid" then HybridFlag=1;
if lastrow then do; * *********************** These are NOT empty do loops;
if HybridFlag=1 then do;
call symputx('foot',"&make Offers Hybrid Cars");
end;
else do;
call symputx('foot',"&make Does Not Have a Hybrid Car");
end;
end;
run;
title "&make Cars";
footnote "&foot";
proc print data=&make noobs;
var Model Type MSRP HybridFlag;
run;
title;footnote;
With you original construct, both %LET statements were executed (before execution of the data step), and the last one was the one that had effect.
If you do not want the flag variable, you can simplify your code like this:
%let make=Honda;
%let foot=&make Does Not Have a Hybrid Car;
data &make(keep=Make Model Type MSRP);
set sashelp.cars;
where upcase(Make)="%upcase(&make)";
if Type="Hybrid" then
call symputx('foot',"&make Offers Hybrid Cars");
run;
title "&make Cars";
footnote "&foot";
proc print data=&make noobs;
var Model Type MSRP;
run;
title;footnote;
Available on demand!
Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.
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.