Input Variable SAS Macro - sas

%let dsin = pre_finalized;
data _null_;
set &dsin. (obs=1);
I also tried
%let dsin = data.pre_finalized;
Is the above the correct way to call my code. It is not the full code. But I am unsure if I am calling the dataset correctly. I keep on getting error logs. Any suggestions?

If i understand your question correctly, you are trying to call a dataset using a macro variable.
Below is the code which i quickly tested and its working.
Please see if this helps.
%let data=sashelp.class;
data abc;
set &data. (obs=1);
run;

Related

SAS date macro and compress function

I am struggling with this compress function in the code below that I am trying to convert.
Old code: (This code works and returns the results below)
data _null_;
%let startdt='2015/11/1';
date_num=compress(&startdt,"'");
call symputx('date_num',date_num);
%put &startdt;
%put &date_num;
run;
This code returns values for the macro variable startdt as 2015/11/1 and datenum as 2015/11/1.
I am trying to achieve similar functionality using macro variables for dates.
New code: (This code gives me an error and I am not able to figure out why)
data _null_;
dt = date();
last_mth_beg = intnx('month',dt,-1,'beginning');
call symput('startdt',put(last_mth_beg,YYMMDDS10.));
date_num=compress(&startdt,"'");
call symputx('date_num',date_num);
%put &startdt;
%put &date_num;
run;
I am getting an error when I run this new code. I would like to get results as in the old code.
Please help. Thank you!
Your first data step is just removing the quotes from your macro variable. You can do this in macro code by either using %sysfunc() to call the compress() function. Or even just use the %scan() function.
%let date_num = %scan(&startdt,1,%str(%'));
In the second one it looks like you are trying to use INTNX() function on the date value. But your macro variables do not contain date values. If you want to treat '2015/11/1' as if it was a date then you will need to use an input function to convert it first.
%let last_mth_beg = %sysfunc(intnx(month,%sysfunc(inputn(&date_num,yymmdd10)),-1,b),yymmdd10);
I am not sure why your old code is not giving you an error. The first time you run it, you should see the error,
WARNING: Apparent symbolic reference DATE_NUM not resolved.
Then, after the data step has run, &DATE_NUM will have a value. You cannot use %PUT inside a data step to display a macro variable you are creating within the data step.
In your second set of code, the value of the STARTDT macro variable you are creating does not have single quotes around it in the first place. If you just run the following, you will get the correct result:
data _null_;
dt = date();
last_mth_beg = intnx('month',dt,-1,'beginning');
call symput('startdt',put(last_mth_beg,YYMMDDS10.));
run;
%put &startdt;
When I run it, I see
2016/11/01

how to display a sentence in the SAS result output window

I wrote a macro using sas. I saved the log in an external txt file, using the following code.
proc printto log="path\log.txt"; run;
%macro loop(num);
for i = 1 : #
data a;
set a;
display &i;
run;
%mend;
% loop(100)
proc printto; run;
My program works like a loop. for i = 1 : 100, do something then i = i +1. I want to display i at the end of each loop, so I know where the program is. I do not want it displayed in log /(the log txt file) because it will be mixed with the log and hard to read. so I can not use put "&i" function.
Please let me know if there is any better place to display i (maybe the result output window?) If so, how to do it please.
The log is the correct place to put this. Many tricks exist to help you make this visible.
The way the log highlights things in different colors is driven by the keywords NOTE:, WARNING:, and ERROR:. You can use those to your advantage if you don't mind slightly misleading log notes.
Turn off excess log messages, or redirect them to another location, during the bulk of the processing. This is very common to be done inside a macro.
Use things like this:
Code:
%put ********************************************************;
%put * ITERATION &i BEGINNING *;
%put ********************************************************;
All that said, it's certainly possible to do what you're asking; the question is, where is it useful for you to see it.
Two suggestions.
First: ods text will output to the results window, but it requires you to have something else printing (it won't just show up on its own). It's not dissimilar to using title, really.
%macro test;
%do i=1 %to 10;
ods text="Running &i. Iteration";
proc print data=sashelp.class;
run;
%end;
%mend test;
%test;
Similarly, you can use ods proclabel to get the Results Explorer window to show the iteration number.
%macro test;
%do i=1 %to 10;
ods proclabel="&i. Iteration";
proc print data=sashelp.class;
run;
%end;
%mend test;
%test;
I like the latter more; it makes it easier to see what's going on.
Both, however, have a major limitation: they're not going to let you see what's going on while the macro is executing, generally. You'll need something for this purpose I suspect that will update a file outside of the SAS environment; anything other than the log will often be sort of 'frozen' while the IDE thinks about doing SAS things.
If you're aiming to use this as sort of a 'how far along are we' monitor, you have several options.
First, a SAS/AF window could possibly do the trick - see Aster, NESUG '92 for an example.
Second, write to a file.
filename monitor "c:\temp\monitor.dat";
%macro test;
%do i=1 %to 100;
data _null_;
file monitor mod;
put "Iteration &i started";
run;
*... do stuff ...;
%end;
%mend test;
%test;
This is basically just making your own secondary log, which seems like perhaps the best compromise here. It does also give you the same information in the log if you have SYMBOLGEN on.
Since you are using PC SAS, in an interactive session, you can use data step PUT statements to write to the log, or the output window. In PC sas the log and the output window but update in real time (different than in EG).
%macro testmsg
(nloop=5
,file=log /* log | print */
)
;
%local i ;
%do i=1 %to &nloop ;
data _null_ ;
file &file ;
x=sleep(3) ;
put "&i" ;
run ;
%end ;
%mend testmsg ;
%testmsg(file=log)
%testmsg(file=print)

Trying to create new dataset using macro sas

I have the following code:
%macro One (Data=, City=);
data &data;
set Dataset1;
Var_new=.;
if State = "CA" and CITYCODE = &City then output;
run;
%mend One;
%One (Data=Bakersfield_CA, City=12540);
%One (Data=Chico_CA City=17020);
I get the first dataset for Bakersfield_CA..but I get error for the second time the macro runs and I don't get any dataset called "CHico_CA".
You're missing a comma in your second macro call. Try
%One (Data=Bakersfield_CA, City=12540);
%One (Data=Chico_CA, City=17020);
In general, though, creating lots of little datasets like this is a bad idea, as it makes your code much more complicated than necessary. What are you trying to do for each city? You can probably do the same thing with your original dataset1 using by-group processing.

SAS: How to assign the output value of a function-like macro?

I am very new using SAS and Im having hard time trying to assign the output value of a function-like macro to a macro variable. After testing, I have check that the value is computed correctly, but once I tried to assign it the program crashes. here you can find the code
%MACRO TP_BULLET(ZCURVE,TAU,YF=1);
/* KEEP ONLY THE ZERO CURVE UNTIL MATURITY*/
DATA _TEMP;
SET &ZCURVE;
IF MATURITY > &TAU THEN DELETE;
RUN;
PROC SQL NOPRINT;
SELECT DISTINCT 1- DF
INTO :NUME
FROM _TEMP
GROUP BY MATURITY
HAVING MATURITY = MAX(MATURITY);
QUIT;
PROC SQL NOPRINT;
SELECT SUM(DF)
INTO :DENO
FROM _TEMP;
QUIT;
PROC DELETE DATA=_TEMP;RUN;
%LET TP = %SYSEVALF(&YF*&NUME / &DENO);
&TP
%MEND TP_BULLET;
%MACRO TESTER2;
%LET K = %TP_BULLET(ZCURVE,TAU,YF=1);
%PUT .......&K;
%MEND TESTER2;
%TESTER2;
The error I am getting is the following
WARNING: Apparent symbolic reference DENO not resolved.
WARNING: Apparent symbolic reference NUME not resolved.
ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric operand is required. The condition was:
1*&NUME / &DENO
So I suppose that the DATA Step is failing to create the sas table _TEMP, but I have no idea how to solve it. Thanks in advance for any help or sugestion
This is NOT a 'function like' macro - you are mixing SAS Macro language and Base SAS. Remember that the SAS Macro language is a code generator - and you are generating code, which is currently something like:
%let K=data _temp; set ZCURVE; ....
note how the above is not what you wanted to assign to the macro variable K.
To help with this, try running your macro with options mprint - this will show you the code being generated by your macro.
If you want your macro to act like a function, then (at a minimum) you should find NO code being generated via the mprint option..
All philosophical issues aside, you could add a parameter to your macro that specifies the new macrovariable (mv) that you want to create. So instead of
%Let k = %TP_BULLET(ZCURVE,TAU,YF=1);
you could call
%TP_BULLET(ZCURVE,TAU,mvOutput=k,YF=1);;
Your macro would need to be modified slightly with
%MACRO TP_BULLET(ZCURVE,TAU,mvOutput,YF=1);
%GLOBAL &mvOutput;
........ Same code as above .........
%Let &mvOutput = &TP; *Instead of final line with '&TP';
%MEND;
It is not a very SAS-y way to accomplish it, but it can help keep things more modular and comprehensible if you're working with more programming backgrounds, rather than SAS.

Convert the number of observations in a dataset into a macro variable

I am trying to determine the number of observations in a dataset, then convert this number into a macro variable that i can use as part of a loop. I've searched the web for answers and not had much luck. I would post some example code I've tried but I have literally no idea how to approach this.
Could anybody assist?
Thanks
Chris
SAS stores dataset information, such as number of observations, separately, so the key is to access this information without having to read in the entire dataset.
The following code will do just that, the if 0 part is never true so the dataset isn't read, however the information is.
data _null_;
if 0 then set sashelp.class nobs=n;
call symput('numobs',n);
stop;
run;
%put n=&numobs;
You can also get it from dictionary.tables like this:
proc sql noprint;
select nobs into :nobs
from dictionary.tables
where libname='YourLibrary' and memname='YourDatasetName';
quit;
Here it is:
Create macro variable:
data _null_;
set sashelp.class;
call symput("nbobs",_N_);
run;
See result:
%put &nbobs;
Use it:
data test;
do i = 1 to &nbobs;
put i;
end;
run;