Calcite | Level 5

## Calculate mean based on given time period

Hi,

This seems to be a fairly easy problem to solve, but for some reason I cannot think of a way to solve it.

I have four macro variables, StartDateMonth, StartDateYear, EndDateMonth and EndDateYear that the user enters in.

The variable names in my data set are in the form of Rate_01_2010, Rate_02_2010, Rate_03_2010, Rate_4_2010, ...., Rate_12_2012. I'd like to calculate the average of the rates based on the dates that the user enters.

Example:

%Let StartDateMonth = 6;

%Let StartDateYear = 2010;

%Let EndDateMonth = 3;

%Let EndDateYear = 2012;

Basically, I would want the calculation

Average = mean(Rate_06_2010, Rate_07_2010, ....., Rate_02_2012, Rate_03_2012);

However, I'd like this to be done automatically, based on the inputs.

Thank you for the help!

1 ACCEPTED SOLUTION

Accepted Solutions
Super User

## Re: Calculate mean based on given time period

Maybe this?

%macro RateVars(sm, sy, em,ey);
%local sdate edate d m y vars;
%let sdate = %sysfunc(mdy(&sm,1,&sy));
%let edate = %sysfunc(mdy(&em,1,&ey));
%let d = &sdate;
%let vars = ;
%do %while (&d le &edate);
%let m = %sysfunc(putn(%sysfunc(month(&d)),z2.));
%let y = %sysfunc(putn(%sysfunc(year(&d)),f4.0));
%let vars = &vars Rate_&m._&y;
%let d = %sysfunc(intnx(Month,&d,1));
%end;
&vars
%mend;

Use in data step as:

data new;
set have;
average = mean(of %RateVars (&StartDateMonth,&StartDateYear,&EndDateMonth,&EndDateYear))  ;
run;

6 REPLIES 6
Lapis Lazuli | Level 10

## Re: Calculate mean based on given time period

try:

Average = mean(Rate_&StartDateMonth._&StartDateYear, Rate_%eval(&StartDateMonth+1.)_&StartDateYear,

Rate_%eval(&EndDateMonth.-1)._&EndDateYear, Rate_&EndDateMonth._&EndDateYear);

it will not work at the beginning and the end of a year.

Pyrite | Level 9

## Re: Calculate mean based on given time period

Hi,

One way could be to rearrange your data from wide-to-long, thus having one rate column and a date column.

Then you can use either proc sql or proc summary/means to summarize the rate (column) using a where statement that uses your macro variables, something like this:

data long;

set your_wide_data;

rate = rate_03_2010;

date = mdy(03,01,2010);*I chose the day to be the first (01) since it doesn't seem to matter for your problem;

output;

rate = rate_04_2010;

date = mdy(06,01,2010);

output;

...

rate = rate_06_2012;

date = mdy(06,01,2012);

output;

proc means data = long;

var rate;

where mdy(&StartDateMonth., 01, &StartDateYear. ) <= date <= mdy(&EndDateMonth.,01, &endDateYear.);

run;

or

proc sql noprint;

create table averages_&StartDateMonth as

select avg(rate) as average_rate

from long

where mdy(&StartDateMonth., 01, &StartDateYear. ) <= date <= mdy(&EndDateMonth.,01, &endDateYear.);

quit;

Best of luck,

Anca.

Quartz | Level 8

## Re: Calculate mean based on given time period

You may try below code and see if it works for you. Good Luck.

data _null_;

length varlist \$1000;

retain varlist;

sdate = input(compress("&StartDateYear"||'-'||put(input("&StartDateMonth",best.),z2.)||'-01'),yymmdd10.);

edate = input(compress("&EndDateYear"||'-'||put(input("&EndDateMonth",best.),z2.)||'-01'),yymmdd10.);

do dates = sdate to edate;

if day(dates)=1 then do;

month = put(month(dates),z2.);

year = put(year(dates),4.);

if varlist='' then varlist = 'Rate_'||strip(month)||'_'||strip(year);

else varlist = strip(varlist)||', '||'Rate_'||strip(month)||'_'||strip(year);

output;

end;

end;

call symput('varlist',varlist);

format sdate edate dates date9.;

run;

%put &varlist;

data output;

Average = mean(&varlist);

run;

PROC Star

## Re: Calculate mean based on given time period

If you're lucky, this will be easy.  "Lucky" here means that the rate variables are internally stored in date order with no other variables in between.  PROC CONTENTS will show you that.  In that case, you could just use:

average = mean(of rate_&StartDateMonth._&StartDateYear -- rate_&EndDateMonth._&EndDateYear);

If the variables are in order, but they are interspersed with character variables, it is still possible:

average = mean(of rate_&StartDateMonth._&StartDateYear -numeric- rate_&EndDateMonth._&EndDateYear);

Super User

## Re: Calculate mean based on given time period

Maybe this?

%macro RateVars(sm, sy, em,ey);
%local sdate edate d m y vars;
%let sdate = %sysfunc(mdy(&sm,1,&sy));
%let edate = %sysfunc(mdy(&em,1,&ey));
%let d = &sdate;
%let vars = ;
%do %while (&d le &edate);
%let m = %sysfunc(putn(%sysfunc(month(&d)),z2.));
%let y = %sysfunc(putn(%sysfunc(year(&d)),f4.0));
%let vars = &vars Rate_&m._&y;
%let d = %sysfunc(intnx(Month,&d,1));
%end;
&vars
%mend;

Use in data step as:

data new;
set have;
average = mean(of %RateVars (&StartDateMonth,&StartDateYear,&EndDateMonth,&EndDateYear))  ;
run;

Calcite | Level 5

## Re: Calculate mean based on given time period

Thank you! That works perfectly!

Discussion stats
• 6 replies
• 3104 views
• 9 likes
• 6 in conversation