BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
PetePatel
Quartz | Level 8

Hi,

 

I have a large dataset (20 year period) in the following format:

 

monthnumeratordenominator
Jan-1610200
Feb-1615300
Mar-1620300
Apr-1610150
May-165100
Jun-1630350
Jul-1620400
Aug-1625350
Sep-1615200
Oct-1640450
Nov-1610200
Dec-1640400

 

I need to transform to a quarterly view in the following way.

 

Quarter_endRate
Mar-1622.5%
Jun-1630.0%
Sep-1615.0%
Dec-1620.0%

 

Mar-16 (quarter end) = sum of numerator in Jan-16, Feb-16 and Mar-16 divided by denominator in Jan-16 (quarter start)
= (10+15+20) / 200

 

The logic for the other quarters follow in the same way.

 

I am currently doing this in Excel but it can get messy.

 

Is there a more efficient way of doing this in SAS?

 

Thanks in advance

1 ACCEPTED SOLUTION

Accepted Solutions
ed_sas_member
Meteorite | Level 14

Same update, to take into account the year:

data have;
	infile datalines dlm="09"x;
	input month:monyy. numerator denominator;
	format month monyy.; 
	datalines;
Jan-16	10	200
Feb-16	15	300
Mar-16	20	300
Apr-16	10	150
May-16	5	100
Jun-16	30	350
Jul-16	20	400
Aug-16	25	350
Sep-16	15	200
Oct-16	40	450
Nov-16	10	200
Dec-16	40	400
Jan-17	40	450
Feb-17	10	200
Mar-17	40	400
;
run;
 
data have_q;
	set have;
	Year = year(month);
	Quarter = qtr(month);
run;

data denominator (keep= year quarter denominator) last_month (keep=year quarter month);
	set have_q;
	by year quarter;
	if first.quarter then output denominator;
	if last.quarter then output last_month;
run;

proc means data=have_q sum noprint;
	var numerator;
	by year quarter;
	output out=numerator (drop=_:) sum=sum_numerator;
run;

data want (keep= month Rate rename=(month=Quarter_end));
	merge numerator denominator last_month;
	format Rate percent8.1;
	by year quarter;
	Rate = sum_numerator / denominator;
run;

View solution in original post

10 REPLIES 10
ed_sas_member
Meteorite | Level 14

Hi @PetePatel 

 

Here is one approach to achieve this, using a data step:

data have;
	infile datalines dlm="09"x;
	input month:monyy. numerator denominator;
	format month monyy.; 
	datalines;
Jan-16	10	200
Feb-16	15	300
Mar-16	20	300
Apr-16	10	150
May-16	5	100
Jun-16	30	350
Jul-16	20	400
Aug-16	25	350
Sep-16	15	200
Oct-16	40	450
Nov-16	10	200
Dec-16	40	400
;
run;
 
data have_q;
	set have;
	Quarter = qtr(month);
run;

data want (keep= Quarter_end Rate);
	set have_q;
	by Quarter;
	format month monyy. Rate percent8.1;
	retain numerator_sum;
	retain denominator_sum;
	if first.Quarter then do;
		numerator_sum=0;
		denominator_sum=0;
	end;
	numerator_sum + numerator;
	if first.Quarter then denominator_sum + denominator;
	Rate = numerator_sum / denominator_sum;
	if last.Quarter then output;
	rename month=Quarter_end;
run;
PetePatel
Quartz | Level 8

Thanks Ed, this is really close.

 

It works for the one year period I provided but as soon as you add in more quarters it fails.

 

So if I add on the below to datalines

 

Jan-17 40 450
Feb-17 10 200
Mar-17 40 400

 

Is there a way around this?

ed_sas_member
Meteorite | Level 14

Hi @PetePatel 

 

I have added two statements in the program to take into account the year:

 

Best,

 

data have;
	infile datalines dlm="09"x;
	input month:monyy. numerator denominator;
	format month monyy.; 
	datalines;
Jan-16	10	200
Feb-16	15	300
Mar-16	20	300
Apr-16	10	150
May-16	5	100
Jun-16	30	350
Jul-16	20	400
Aug-16	25	350
Sep-16	15	200
Oct-16	40	450
Nov-16	10	200
Dec-16	40	400
Jan-17	40	450
Feb-17	10	200
Mar-17	40	400
;
run;
 
data have_q;
	set have;
	Year = year(month);
	Quarter = qtr(month);
run;

data want (keep= Quarter_end Rate);
	set have_q;
	by Year Quarter;
	format month monyy. Rate percent8.1;
	retain numerator_sum;
	retain denominator_sum;
	if first.Quarter then do;
		numerator_sum=0;
		denominator_sum=0;
	end;
	numerator_sum + numerator;
	if first.Quarter then denominator_sum + denominator;
	Rate = numerator_sum / denominator_sum;
	if last.Quarter then output;
	rename month=Quarter_end;
run;
ed_sas_member
Meteorite | Level 14

Another option could be to use a proc means:

data have;
	infile datalines dlm="09"x;
	input month:monyy. numerator denominator;
	format month monyy.; 
	datalines;
Jan-16	10	200
Feb-16	15	300
Mar-16	20	300
Apr-16	10	150
May-16	5	100
Jun-16	30	350
Jul-16	20	400
Aug-16	25	350
Sep-16	15	200
Oct-16	40	450
Nov-16	10	200
Dec-16	40	400
;
run;
 
data have_q;
	set have;
	quarter = qtr(month);
run;

data denominator (keep=quarter denominator) last_month (keep=quarter month);
	set have_q;
	by quarter;
	if first.quarter then output denominator;
	if last.quarter then output last_month;
run;

proc means data=have_q sum noprint;
	var numerator;
	by quarter;
	output out=numerator (drop=_:) sum=sum_numerator;
run;

data want (keep= month Rate rename=(month=Quarter_end));
	merge numerator denominator last_month;
	format Rate percent8.1;
	by quarter;
	Rate = sum_numerator / denominator;
run;

ed_sas_member
Meteorite | Level 14

Same update, to take into account the year:

data have;
	infile datalines dlm="09"x;
	input month:monyy. numerator denominator;
	format month monyy.; 
	datalines;
Jan-16	10	200
Feb-16	15	300
Mar-16	20	300
Apr-16	10	150
May-16	5	100
Jun-16	30	350
Jul-16	20	400
Aug-16	25	350
Sep-16	15	200
Oct-16	40	450
Nov-16	10	200
Dec-16	40	400
Jan-17	40	450
Feb-17	10	200
Mar-17	40	400
;
run;
 
data have_q;
	set have;
	Year = year(month);
	Quarter = qtr(month);
run;

data denominator (keep= year quarter denominator) last_month (keep=year quarter month);
	set have_q;
	by year quarter;
	if first.quarter then output denominator;
	if last.quarter then output last_month;
run;

proc means data=have_q sum noprint;
	var numerator;
	by year quarter;
	output out=numerator (drop=_:) sum=sum_numerator;
run;

data want (keep= month Rate rename=(month=Quarter_end));
	merge numerator denominator last_month;
	format Rate percent8.1;
	by year quarter;
	Rate = sum_numerator / denominator;
run;
PetePatel
Quartz | Level 8

Works perfectly, thank you.

PeterClemmensen
Tourmaline | Level 20

Is this for reporting purposes or do you need a SAS data set?

PetePatel
Quartz | Level 8

For reporting but required in SAS to merge onto other datasets.

novinosrin
Tourmaline | Level 20

Hi @PetePatel  Nice to see the question has been answered in very legible terms. Good morning, Assuming your sample represents your sample and is neatly sorted by calendar month, this presents a case for nice application of groupformats akin to what we are used to in procedures. One would think, why not use a procedure, well datastep is more of a work horse than readymeals, the options plethora are staggering

 

data have;
	infile datalines ;
	input month:monyy. numerator denominator;
	format month monyy.; 
	datalines;
Jan-16	10	200
Feb-16	15	300
Mar-16	20	300
Apr-16	10	150
May-16	5	100
Jun-16	30	350
Jul-16	20	400
Aug-16	25	350
Sep-16	15	200
Oct-16	40	450
Nov-16	10	200
Dec-16	40	400
Jan-17	40	450
Feb-17	10	200
Mar-17	40	400
;
run;

data want;
 call missing(Quarter_end);
 do until(last._m);
  set have(rename=month=_m);
  by _m groupformat;
  format _m yyq6.;
  Quarter_end=_m;
  if first._m then _d=denominator;
  _n=sum(numerator,_n);
 end;
 Rate=_n/_d;
 format rate percent8.2 Quarter_end monyy7.; 
 keep Quarter_end rate;
run;

All the best!

PetePatel
Quartz | Level 8

Thank  you novinosrin, I didn't know you could use a groupformat in such a way.

Ready to join fellow brilliant minds for the SAS Hackathon?

Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.

Register today!
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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 10 replies
  • 799 views
  • 4 likes
  • 4 in conversation