What is it that you want out of that? Why are you doing all of that crazy macro stuff?
https://forum.wordreference.com/threads/idiom-for-doing-something-simple-in-a-lengthier-way.3366230/
%let vars=a b c;
data all;
set a b;
keep &vars;
run;
proc distance data=all out=Dist(keep=Dist1 rename=Dist1=d) method=Euclid;
var interval(&vars);
run;
data want;
set b;
set dist(firstobs=2) ;
run;
Obs a b c d 1 87 78 60 29.2916 2 99 45 77 26.2679 3 103 95 73 27.8927
I definitely don't quite understand what you're trying to do overall, not sure why SET doesn't work as well? I feel like this could simplify your problem. However, assuming you want to stick with the approach identified, see a simplified solution below.
This would give the same solution as below - no macro logic besides the names and number of them needed which is trivial to get.
data final;
if _n_ =1 then set one;
set many_dist;
array diff(&number_vars) diff1-diff3;
array key(&number_vars) key:;
array _refs(&number_vars) &vars;
do i=1 to &number_vars.;
diff(i) = key(i) - _refs(i);
end;
run;
Some notes:
data a;
input id $ a b c d e;
datalines;
001 100 70 85 86 94
;
data b;
input id $ a b c;
datalines;
002 87 78 60
003 99 45 77
004 103 95 73
;
%macro example (vars);
%let number_vars = %sysfunc(countw(&vars)) ;
data one;
set a (keep=id &vars);
/*One record only*/
array _myvars(&number_vars) &vars.;
call symputx('value_list', catx(' ', of _myvars(*)));
run;
data many;
set b (keep=id &vars);
/*Multiple records*/
run;
*Preparing dataset the calculation of the Euclidean distance;
data all;
set one many;
run;
*Calculating the Euclidean distance;
proc distance data=all out=Dist (keep=dist1) method=Euclid;
var interval(&vars);
run;
data dist;
set dist;
if _n_=1 then
delete;
rename dist1=d;
run;
*Matching each object with a distance value;
data many_dist;
merge many dist;
*Renaming &vars before merging back with ‘One’;
rename id=idcode;
%do i=1 %to &number_vars.;
rename %scan(&vars., &i.)=key_&i.;
%end;
run;
data final;
merge one many_dist;
array diff(&number_vars) diff1-diff3;
array key(&number_vars) key:;
array _refs(&number_vars) _temporary_ (&value_list);
do i=1 to &number_vars.;
diff(i)=key(i) - _refs(i);
end;
run;
data final2;
if _n_=1 then
set one;
set many_dist;
array diff(&number_vars) diff1-diff3;
array key(&number_vars) key:;
array _refs(&number_vars) &vars;
do i=1 to &number_vars.;
diff(i)=key(i) - _refs(i);
end;
run;
proc datasets lib=work;
delete one many: all z dist;
run;
%mend;
%example (vars=a b c)
%macro example (vars);
%let number_vars = %sysfunc(countw(&vars)) ;
*Preparing dataset the calculation of the Euclidean distance;
data all;
set a (keep=id &vars) b (keep=id &vars);
run;
*Calculating the Euclidean distance;
proc distance data=all out=Dist (keep=dist1) method=Euclid;
var interval(&vars);
run;
data dist;
set dist;
if _n_=1 then
delete;
rename dist1=d;
run;
*Matching each object with a distance value;
data many_dist;
merge b (keep = id &vars) dist;
*Renaming &vars before merging back with ‘One’;
rename id=idcode;
%do i=1 %to &number_vars.;
rename %scan(&vars., &i.)=key_&i.;
%end;
run;
data final;
if _n_=1 then
set a (keep = id &vars);
set many_dist;
array diff(*) diff1-diff&number_vars;
array key(*) key:;
array _refs(*) &vars;
do i=1 to dim(diff);
diff(i)=key(i) - _refs(i);
end;
run;
proc datasets lib=work;
delete many: all dist;
run;
%mend;
%example (vars=a b c)
This is the full simplified version that matches the results.
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
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.