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

I'm trying to use an array to change my dataset from multiple rows per patient to a single row per patient with many columns.  It was working perfectly until I tried adding a second array for another medication type and goofed something up.  I'm not seeing what I messed up; need another pair of eyes to take a look.  Here's the code I'm using.  The error is array subscript out of range, and the log shows that I=11.   Please help!!!

 

DATA MEDS ;
   SET GET_COUNTS ;
   BY PATIENT_ID ;
   FORMAT CLINDAMYCIN CEPHALOSPORIN FLOUROQUINOLONE VANCOMYCIN PPI 1. ;

   RETAIN CLINDAMYCIN CEPHALOSPORIN FLOUROQUINOLONE VANCOMYCIN PPI ;

   * 1 = YES, 0 = NO ;
   CLINDAMYCIN = 0 ;
   CEPHALOSPORIN = 0 ;
   FLOUROQUINOLONE = 0 ;
   VANCOMYCIN = 0 ;
   PPI = 0 ;

   ARRAY ABX[*] $ 15. ABX1 - ABX10 ;

   RETAIN ABX1 - ABX10 ;

   IF FIRST.PATIENT_ID THEN DO I = 1 TO 10 ;
      ABX[I] = ' ' ;
      END ;
   
   ABX[ABX_COUNT] = ABX_NAME ;
   
   DO I = 1 TO 10 ;
      IF ABX[I] = 'CLINDAMYCIN' THEN CLINDAMYCIN = '1' ;
   END ;
   DO I = 1 TO 10 ;
      IF ABX[I] IN ('CEFUROXIME', 'CEFPROZIL', 'CEFACLOR', 'CEFTRIAXONE', 'CEFOTAXIME' )
         THEN CEPHALOSPORIN = '1' ;
   END ;
   DO I = 1 TO 10 ;
      IF ABX[I] IN ('CIPROFLOXACIN', 'LEVOFLOXACIN', 'GATIFLOXACIN', 'MOXIFLOXACIN', 'OFLOXACIN' )
         THEN FLOUROQUINOLONE = '1' ;
   END;
   DO I = 1 TO 10 ;   
      IF ABX[I] = 'VANCOMYCIN' THEN VANCOMYCIN = '1' ;
   END ;

   IF LAST.PATIENT_ID THEN OUTPUT ;

   KEEP PATIENT_ID AGEGRP GENDER STUDY_GRP ABX_COUNT ABX1 - ABX10 CLINDAMYCIN CEPHALOSPORIN FLOUROQUINOLONE VANCOMYCIN PPI ;
RUN ;

1 ACCEPTED SOLUTION

Accepted Solutions
Kurt_Bremser
Super User

This statement

ABX[ABX_COUNT] = ABX_NAME ;

is the most likely culprit. Variable I will always be 11 after a do loop that counts to 10 has finished.

So look for the values of abx_count in your dataset.

View solution in original post

6 REPLIES 6
RW9
Diamond | Level 26 RW9
Diamond | Level 26

Please post test data in the form of a datastep in teh post (use the {i} window to add code in).  Its also very hard to read your code which is all in upcase.  From what I can tell roughly all you are doing is setting a flag based on the drug, so you could just transpose the data.  Its very hard to tell however without some inputs and some required output.  Note, I would avoid using real information (I recognise those drug names for instance).

 

Adding example:

proc transpose data=have out=inter1 prefix=abx;
  by patient_id;
  var abx_med;
run;
proc transpose data=have out=inter2 prefix=other;
  by patient_id;
  var othervar;
run;
data want;
  merge inter1 inter2;
  by patient_id;
  abx_c=catx(',',of abx:);
  do i=1 to countw(abx_c,",");
    select(scan(abx_c,i,","));
      when("CEF.....)  var1=1;
      ...
    end;
  end;
run;

Do also note that whilst you make the drug variables numeric, you are assigning characters to them later in your code, not good practice:

 CLINDAMYCIN = 0 ;   <= numeric
  IF ABX[I] = 'CLINDAMYCIN' THEN CLINDAMYCIN = '1' ;  <=char
   

Kurt_Bremser
Super User

This statement

ABX[ABX_COUNT] = ABX_NAME ;

is the most likely culprit. Variable I will always be 11 after a do loop that counts to 10 has finished.

So look for the values of abx_count in your dataset.

tmtemples
Fluorite | Level 6

Thank you.  Is there a way to stop the DO loop once the desired result is found?

tmtemples
Fluorite | Level 6

You are correct!  I have an initial count of 0.  The eleven was not the problem! 

 

Thank you!!!

Astounding
PROC Star

Yes, although it will require that you fix some earlier details.  Right now, you have:

 

DO I = 1 TO 10 ;
      IF ABX[I] = 'CLINDAMYCIN' THEN CLINDAMYCIN = '1' ;
   END ;

 

Since CLINDAMYCIN was created as a numeric variable, remove the quotes around '1'. 

 

To end the loop once a match is found:

 

DO I = 1 TO 10  until (CLINDAMYCIN = 1);
      IF ABX[I] = 'CLINDAMYCIN' THEN CLINDAMYCIN = 1 ;
   END ;

 

Note that this has nothing to do with your original problem, which still requires investigating ABX_COUNT.

ballardw
Super User

Alternatively to the "until" approach you can use a leave instruction.

Inside any do loop:

 

do <loop control>;

   <code>;

   if condition is true then Leave;

   <more code to execute when the condition is not true>

end;

 

Will exit the do loop before hitting the bottom end

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
  • 6 replies
  • 2391 views
  • 1 like
  • 5 in conversation