BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
shakednav
Fluorite | Level 6

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!

1 ACCEPTED SOLUTION

Accepted Solutions
ballardw
Super User

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.

View solution in original post

11 REPLIES 11
ballardw
Super User

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.

shakednav
Fluorite | Level 6
The input for both macros is an empty array or a string (it doesn’t matter)
that contains names of laboratory blood test (WBC,RBC,HGB,..).

I need to write a macro that creates an empty numeric array that composed
from 3 vars for each blood test-
WBC WBC-UL WBC-LL RBC RBC-LL RBC-UL .....

And another macro that creates an empty character array for measure units
for each lab test-

WBC-UNT RBC-UNT ..

just an empty arrays where the macro creates them dynamically.
Reeza
Super User

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!


 

shakednav
Fluorite | Level 6
Thank you!
Those variables are given (I’m writing them in the code).
Reeza
Super User
How? If we don't know how you're specifying it, we don't what the input is? I'm assuming this is also dynamic to some degree?
shakednav
Fluorite | Level 6

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

Reeza
Super User
Hyphens aren't part of a valid SAS name, can we assume you mean underscore or are you using literals? Which would make it:

WBC 'WBC-LL'n 'WBC-UL'n
shakednav
Fluorite | Level 6
Didn’t know that haha
Underscore is fine, doesn’t matter to me
Reeza
Super User
%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

 

ballardw
Super User

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.

shakednav
Fluorite | Level 6
Works great!
Thank you

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

Register now!

How to Concatenate Values

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 11 replies
  • 966 views
  • 4 likes
  • 3 in conversation