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.
April 27 – 30 | Gaylord Texan | Grapevine, Texas
Walk in ready to learn. Walk out ready to deliver. This is the data and AI conference you can't afford to miss.
Register now and lock in 2025 pricing—just $495!
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.
Ready to level-up your skills? Choose your own adventure.