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

I am stuck trying to read a macro variable containing a list of values by using the %scan function to find which list is going to be scanned for a value. Here is an example:

1. I have the following list;

%let list_cci=MI CHF CVD PVD DEM CPD CTDRD PUD MLD diab_wc diab_c P_H RD CAN MSLD MC HIV;

2. There are lists created named after each values of the list_cci list;

%let MI=410 412;

%let CHF=39891 40201 40211 4291 40401 40403 40411 40413 40491 40493 4254 4255 4257 4258 4259 428;

...

3. The idea is that I want to scan the list, assign a value to a macro variable, and then use that macro variable to tell sas which list to scan for another value. I need to do this in 2 steps because the variable name (MI, CHF, CVD, etc.) is important. However, when

4. Here is what I have done so far, within 2 %do loops that run from 1 to &i and &j:

%let diagname = &%scan(&list_cci.,&i.);

%put &diagname; /*gives me e.g. &MI */

%let var=%scan(&diagname,&j.); /*--->here I expect it would scan the MI list, because &MI is put in the %scan function*/

%put &var; /* but all I get is the jth value from the &list_cci list... even though %put &diagname; gives me &MI!*/

Any ideas why it would scan the first list when I ask to basically %scan(&MI,&j.)? Any other idea how I could solve this?

1 ACCEPTED SOLUTION

Accepted Solutions
Astounding
PROC Star

A few issues have arisen here.  Let's go back to the original problem and modify the approach slightly.

Don't try to assign a value that includes an ampersand.  Try to assign MI, instead of &MI as the value of &DIAGNAME.  That should be easy enough.

Then to retrieve the value of &MI, refer to &&&DIAGNAME.  That should take care of everything.

Good luck.

View solution in original post

11 REPLIES 11
ballardw
Super User

I think what you may be looking for is %let var = %scan(&&diagname,&j);  You want the referenced variable to be evaluated so need the extra &

Also, in some cases ending your macro variables end with a period all the time will result in unexpected results when they concatenate to something undesired.

jorondo
Calcite | Level 5

the ampersand was already added when defining the diagname variable, %let diagname=&%scan(&list_cci.,&i.);

the problem here is that the &diagname variable, even though it gets assigned the right value (&MI for example), when used in the %scan(&diagname,&j.), it browses the first list, as if I hand entered %scan(list_cci,&j.)...

Just to be sure I tried what you said but it's the same as putting the ampersand when defining the diagname macro variable

Amir
PROC Star

Hi,

I just tried your lines of code, setting i and j to 1:

%let list_cci=MI CHF CVD PVD DEM CPD CTDRD PUD MLD diab_wc diab_c P_H RD CAN MSLD MC HIV;

%let MI=410 412;

%let CHF=39891 40201 40211 4291 40401 40403 40411 40413 40491 40493 4254 4255 4257 4258 4259 428;

%let i=1;

%let j=1;

%let diagname = &%scan(&list_cci.,&i.);

%put &diagname; /*gives me e.g. &MI */

%let var=%scan(&diagname,&j.);

%put &var;

and var had a value of 410. Is that what you were expecting?

Regards,

Amir.

jorondo
Calcite | Level 5

it is... which is weird! I found out something: if I put spaces before and after the = sign, I get 410. If I don't (and use j and i=1), I get "scan"... I didn't know spaces around equal signs would influence the result?!


Thanks a lot for that!

tish
Calcite | Level 5

That does not sound like a good result. Spaces don't usually make a difference (except I was counting spaces above to figure how how many codes were in the diagnosis lists). I'd suggest being careful about the extraneous ampersands. For example, in the original code, you have: %let diagname = &%scan(&list_cci.,&i.); I think that first ampersand is unnecessary here and wonder if it's causing your problem.

jorondo
Calcite | Level 5

You are right, I was wrong, it's not working. The thing that bugs me is I need to put the ampersand besore the scan function in order that the value of &diagname be &MI and not only MI, so that when I do the %scan on &diagname, it doesnt scan "MI" but rather "&MI", hence the list contained in the &MI variable... that's what I've been trying to figure out

tish
Calcite | Level 5

My hunch is that the issue is with the do loops. In the following code, I nest them and provide a dynamic end point to the inner loop. You should do that for the outer loop too, but your code gives list for only the first two:

%let list_cci=MI CHF CVD PVD DEM CPD CTDRD PUD MLD diab_wc diab_c P_H RD CAN MSLD MC HIV;

%let MI=410 412;

%let CHF=39891 40201 40211 4291 40401 40403 40411 40413 40491 40493 4254 4255 4257 4258 4259 428;

%do i = 1 %to 2;

  

   %let diagname = %scan(&list_cci, &i);

   %let number_of_diagnosis_codes = %eval(%sysfunc(count(&diagname, %str( )))+1);

  

   %do j = 1 %to &number_of_diagnosis_codes;

  

      ... do something...

  

   %end;

%end;

Hope this helps,

Tish

Astounding
PROC Star

A few issues have arisen here.  Let's go back to the original problem and modify the approach slightly.

Don't try to assign a value that includes an ampersand.  Try to assign MI, instead of &MI as the value of &DIAGNAME.  That should be easy enough.

Then to retrieve the value of &MI, refer to &&&DIAGNAME.  That should take care of everything.

Good luck.

jorondo
Calcite | Level 5

That works! thanks a lot. If I may ask, why 3 &'s? Not sure about the logic behind this..

Astounding
PROC Star

SAS resolves these macro strings in pieces, from left to right.  There are two pieces in &&&DIAGNAME:  && and &DIAGNAME.

&& resolves into &

&DIAGNAME resolves (in this case) to MI.

So the combined string resolves to &MI.  Then SAS notices it still needs to re-scan the string because macro resolution isn't yet complete.

Tom
Super User Tom
Super User

SAS will scan the code twice to resolve the macro references.  On the first pass && is resolved to & and &diagname is resolved to its value (say MI).  So now on the next pass you have &MI which will resolve to the list ICD9 codes.

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

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
  • 1384 views
  • 1 like
  • 6 in conversation