Hi there,
I need to write a macro that creates an array for the following usage:
1. Macro that gets a list of blood tests (i.e., WBC,RBC,HGB,etc.) and returns an empty numeric array with the following structure: array LAB{} WBC WBC-LL WBC-UL RBC RBC-LL RBC-UL... (LL and UL stands for lower/upper limits of the blood tests).
2. Macro that get the same list of blood tests and returns a character array LAB-UNITS{} WBC-UNT RBC-UNT.. (UNT stands for the measure unit of the test).
Another question - after using those arrays, how can I automatically order the columns in this order at the data set:
WBC WBC-LL WBC-UL WBC-UNT RBC RBC-LL RBC-UL RBC-UNT ...
i.e., combining those two arrays in a pattern that makes sense.
Thank you!
strongly suspect that for any actual use involving these values that you would likely be better off with array definitions as:
array LAB{} WBC RBC HGB ; array ll{} WBC_LL RBC_LL HGB_LL ; array ul{} WBC_UL RBC_UL HGB_UL ; array UNITS{} WBC_UNT RBC_UNT HGB_UNT;
That way the same index value points to the related value in all 4 places. Anything with the groups of three is going to involve a lot of skipping around with index values and may be harder to understand and maintain.
But here's one way
%macro vll(list=); %let longlist=; %do i=1 %to %sysfunc(countw(&list.)); %let longlist= &longlist. %scan(&list,&i) %scan(&list,&i)_ll %scan(&list,&i)_ul; %end; &longlist %mend; data example; array badname %vll(list= WBC RBC HGB); run;
Note that it is important not to have semicolon after the last &longlist in the macro. If you do then the resolution of the macro would include the semicolon and for many uses of the variables could cause problems. You might use this macro to create part of a variable list for any use. So if you had some keep statement like
Keep %vll(list= WBC RBC HGB) anothervar thisvar thatvar;
if there is a ; at the end of that last &longlist variable in the macro it would resolve to
Keep WBC WBC_ll WBC_ul RBC RBC_ll RBC_ul HGB HGB_ll HGB_ul; anothervar thisvar thatvar;
The extra semicolon would terminated the Keep statement early leaving the last three variables to create syntax errors.
DO NOT attempt to use this macro with the values of data step varibles in any way. This sort of macro resolves at the data step or procedure compilation time creating syntax and could not "see" any variable values.
Please provide some example input data and what the result should be for that example.
There is very little reason to worry about the order of variables in a SAS data set. If another application or user wants to see the variables in a specific order than use an appropriate tool to create the output in the needed order.
Do you mean a list of variables? I think you want to create a list of variables.
Arrays don't really have a context in SAS beyond shortcuts to variables.
Here is a reference that illustrates how to refer to variables and datasets in a short cut list which may be useful.
https://blogs.sas.com/content/iml/2018/05/29/6-easy-ways-to-specify-a-list-of-variables-in-sas.html
1. Where does the list of blood tests come from? Is it always adding LL/UL to each one?
2. Same as above, where does the list come from?
@shakednav wrote:
Hi there,
I need to write a macro that creates an array for the following usage:
1. Macro that gets a list of blood tests (i.e., WBC,RBC,HGB,etc.) and returns an empty numeric array with the following structure: array LAB{} WBC WBC-LL WBC-UL RBC RBC-LL RBC-UL... (LL and UL stands for lower/upper limits of the blood tests).
2. Macro that get the same list of blood tests and returns a character array LAB-UNITS{} WBC-UNT RBC-UNT.. (UNT stands for the measure unit of the test).
Another question - after using those arrays, how can I automatically order the columns in this order at the data set:
WBC WBC-LL WBC-UL WBC-UNT RBC RBC-LL RBC-UL RBC-UNT ...
i.e., combining those two arrays in a pattern that makes sense.
Thank you!
Nope.
This is the pseudo code:
/*Have*/
array LAB{} WBC RBC HGB //Entered manually, in any alternative way
/* Want */
array LAB{} WBC WBC-LL WBC-UL RBC RBC-LL RBC-UL HGB HGB-LL HGB-UL
array UNITS{} WBC-UNT RBC-UNT HGB-UNT
%let list = WBC RBC;
%macro list_all(input_list= );
%let nwords = %sysfunc(countw("&input_list"));
%put &nwords.;
%do i=1 %to &nwords;
%let word = %scan(&input_list, &i.);
&word.
&word._UL
&word._LL
%end;
%mend;
options symbolgen mprint;
%list_all(input_list = &list);
data demo;
set sashelp.class;
array myArray(*) %list_all(input_list=&list);
do i=1 to dim(myArray);
myArray(i) = 1;
end;
run;
There's a bug in there somewhere but it also works and I don't have more time today. Hopefully it helps you get started or someone else started :).
@shakednav wrote:
Didn’t know that haha
Underscore is fine, doesn’t matter to me
strongly suspect that for any actual use involving these values that you would likely be better off with array definitions as:
array LAB{} WBC RBC HGB ; array ll{} WBC_LL RBC_LL HGB_LL ; array ul{} WBC_UL RBC_UL HGB_UL ; array UNITS{} WBC_UNT RBC_UNT HGB_UNT;
That way the same index value points to the related value in all 4 places. Anything with the groups of three is going to involve a lot of skipping around with index values and may be harder to understand and maintain.
But here's one way
%macro vll(list=); %let longlist=; %do i=1 %to %sysfunc(countw(&list.)); %let longlist= &longlist. %scan(&list,&i) %scan(&list,&i)_ll %scan(&list,&i)_ul; %end; &longlist %mend; data example; array badname %vll(list= WBC RBC HGB); run;
Note that it is important not to have semicolon after the last &longlist in the macro. If you do then the resolution of the macro would include the semicolon and for many uses of the variables could cause problems. You might use this macro to create part of a variable list for any use. So if you had some keep statement like
Keep %vll(list= WBC RBC HGB) anothervar thisvar thatvar;
if there is a ; at the end of that last &longlist variable in the macro it would resolve to
Keep WBC WBC_ll WBC_ul RBC RBC_ll RBC_ul HGB HGB_ll HGB_ul; anothervar thisvar thatvar;
The extra semicolon would terminated the Keep statement early leaving the last three variables to create syntax errors.
DO NOT attempt to use this macro with the values of data step varibles in any way. This sort of macro resolves at the data step or procedure compilation time creating syntax and could not "see" any variable values.
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.