I am not sure I follow what exactly the question is.
Are you asking how to extend the steps in your macro to allow you to process all three Y variables in one pass? So your macro call might look like:
%m_concaveness(data=_concave_, x=x, y=y1 y2 y3, out=_out);
If so then add some macro logic that will add the extra statements to allow each step to handle multiple Y variables. So for example adding more assignment statements to the first data step, and more selected columns to SQL select statements.
Or are you asking how to extend the macro so that you can pass in a grouping variable?
So your macro calls might look like:
%m_concaveness(data=_concave_,group=p,x=x, y=y1, out=_out_y1);
If so then add proper BY groups into the steps in the macro.
So something like:
%macro m_concaveness(data=,group=,x=, y=, out=);
proc sort data=&data;
by &group &x;
run;
data _temp_concave;
set &data;
by &group;
lag_y = lag(&y);
dy = dif(&y);
if first.&group then call missing(lag_y,dy);
run;
data _prep;
merge &data (rename=(&y=_y_prev &x=_x_prev))
&data
&data (firstobs=2 rename=(&y=_y_next &x=_x_next))
;
by &group ;
run;
proc sql noprint;
create table _second_diff as
select a.group
,a.&x as x_val
,a.&y as y_val
,(c.&y - 2*a.&y + b.&y) as second_diff
from &data as a
left join &data as b
on a.&group=b.&group
and a.&x > b.&x
and not exists
(select 1 from &data as c2
where c2.group=a.group
and c2.group=b.group
and c2.group=c.group
and c2.&x > b.&x
and c2.&x < a.&x)
left join &data as c
on a.&group=b.&group
and a.&x < c.&x
and not exists
(select 1 from &data as c3
where c3.group=a.group
and c3.group=a.group
and c3.group=c.group
and c3.&x < c.&x and c3.&x > a.&x)
where b.&y is not null and c.&y is not null
;
quit;
proc means data=_second_diff noprint;
by &group ;
var second_diff;
output out=&out mean=mean_concavity sum=sum_concavity
css=variance_concavity /*concaveness*/ n=n_points
;
run;
/* This step does nothing
data &out; set &out; run;
*/
proc sql;
create table &out as
select group
, avg(second_diff) as mean_concavity label="(Mean Concavity)"
, avg(abs(second_diff)) as mean_abs_concavity label="(Mean Absolute Curvature)"
, sum(second_diff) as net_concavity label="(Net Concavity)"
, count(*) as valid_points
from _second_diff
group by &group
;
quit;
proc datasets lib=work nolist;
delete _second_diff _temp_concave _prep;
quit;
proc print data=&out noobs;
title "Curve Overall Concaveness Measurement";
run;
%mend;
... View more