BookmarkSubscribeRSS Feed
KrisG
Calcite | Level 5
I'm trying to run a macro that looks at data at different time periods. Currently I have it looking at time periods on a continuous loop, i.e. from 1 month to 12 months. I want to be able to look at a set of specific time periods instead of a continuous list.

For example, I'd like to look at time periods 1,3,6,9,12,18,24 instead of having to run it from 1 to 24.

I'll post my code below and point out where I need it to be changed.

I know that I can do this outside of the macro language, but for the purposes of naming my data sets and identifying them later on for more analysis I believe I have to do this in a macro setting. Any help at all would be appreciated.




%macro dosql;

%do j = 0 %to 11;
%do i = 1 %to 24;

proc sql;
create table time_&j. as
select
case_nbr,
sqnc_nbr,
dflt_sts_cd,
ft_in_eps_3mnth_delq_dt,
dflt_cyc_dt
from sf.sfdw_default_history
where ft_in_eps_3mnth_delq_dt <= intnx('month',"15&m.&yr."d,&j.,'end')
and ft_in_eps_3mnth_delq_dt >= intnx('month',"15&m.&yr."d,&j., 'beginning')
order by case_nbr, sqnc_nbr;
quit;

data time_&j.;
set time_&j.;
format status $12. time.2;
status = '.';
time = '.';
run; quit;

proc sql;
create table time_&j._&i. as
select *
from time_&j.
where dflt_cyc_dt <= intnx('month',ft_in_eps_3mnth_delq_dt,&i., 'end')
order by case_nbr, sqnc_nbr;
quit;

data time_&j._&i.;
set time_&j._&i.;
by case_nbr;
if (last.case_nbr = 0) then delete;
run; quit;

data time_&j._&i.;
set time_&j._&i.;
time = "&i.";
eval_time = intnx('month',ft_in_eps_3mnth_delq_dt,&i., 'end');
format eval_time date9.;
run; quit;

data time_&j._&i.;
set time_&j._&i.;
by eval_time;
if eval_time > "&cutoff."d then delete;
run; quit;

data master_data;
set time_0 time_&j._&i.;
run; quit;

%end;
%end;
%mend;
options mprint;
%dosql;






So where it has i = 1 %to 24
I want to run it over a discrete list of numbers rather than all 24

Thanks again,

Kris G
7 REPLIES 7
Robert_Bardos
Fluorite | Level 6
This piece of code might give you an idea
[pre]
%macro doit(b=) ;
%let i = 1 ;
%do %until(%scan(&b,&i) eq) ;
%put &i %scan(&b,&i) ;
%let i = %eval(&i+1) ;
%end ;
%mend ;

%let a = 1 3 6 9 12 18 24 ;

%doit(b=&a) ;
[/pre]
KrisG
Calcite | Level 5
If i use that code provided, do i leave the references to "i" still when naming the datasets?

for example, where I name a set time_&j._&i.

Or where I have &i. listed, is there something else I have put there instead in order to have the files take on those discrete values.
sbb
Lapis Lazuli | Level 10 sbb
Lapis Lazuli | Level 10
Suggest you explore executing the code by adding the statement below which will reveal the processing logic/flow:

OPTIONS SOURCE SOURCE2 MACROGEN SYMBOLGEN MPRINT;

And consider adding MLOGIC as well.

Scott Barry
SBBWorks, Inc.
Robert_Bardos
Fluorite | Level 6
My code sample lacked a bit of clearness obviously.
In order to use the discrete values replace

%put &i %scan(&b,&i) ;

by e.g.

%let disc_i = %scan(&b,&i) ;

and use &disc_i in place of your &i.

Apply similar logic for your &j variable.

Hope this clears the mud a bit.
Robert
KrisG
Calcite | Level 5
Thank you for the help, i was able to make it work with your code.

Kris G
SUN59338
Obsidian | Level 7
in open code data step, this will work also:
data test;
do i= 1, 3, 4, 28;
output;
end;
run;
Bill
Quartz | Level 8
you could use %if &i=1 or &i=3 or &i=6 %then %do;

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

How to Concatenate Values

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 7 replies
  • 3252 views
  • 0 likes
  • 5 in conversation