BookmarkSubscribeRSS Feed
Baba9
Obsidian | Level 7

Hello,

I would appreciate if you can advise regarding how I would conditionally process the do loops below :

data test;
set test1;
if Year <= 2016 then process 35 diag codes
array _diag_code (35)$ DIAG_CODE_: ;
 
 do i=1 to 35;
 IF SUBSTR(_diag_code{i},1,4) in : ('B182') or SUBSTR(_diag_code{i}, 1,3) in ('C22','K70', 'K71', 'K72', 'K73', 'K74', 'K75', 'K76', 'K77', 'R18')  then DIAG=1;
   end;
 if DIAG=1 ;
 array _diag_code (50)$ DIAG_CODE_: ;
 If year >2017 then process 50 diag codes
 do i=1 to 50;
 IF SUBSTR(_diag_code{i},1,4) in : ('B182') or SUBSTR(_diag_code{i}, 1,3) in ('C22','K70', 'K71', 'K72', 'K73', 'K74', 'K75', 'K76', 'K77', 'R18')  then DIAG=1;
   end;
 if DIAG=1 ;
run;
7 REPLIES 7
jimbarbour
Meteorite | Level 14

Is Year part of the Test1 dataset?  Or is Year provided separately somehow in advance?

 

If year is separate, you can use a macro variable as in the first example below.   This example will work in SAS 9.4 M5 or newer.  It will not work in M4 and prior.

data test;
	set test1;
	array _diag_code (*) $ DIAG_CODE_: ;

	%IF	&Year	<=	2016	%THEN
		%DO;
			do i=1 to 35;
			IF SUBSTR(_diag_code{i},1,4) in : ('B182') or SUBSTR(_diag_code{i}, 1,3) in ('C22','K70', 'K71', 'K72', 'K73', 'K74', 'K75', 'K76', 'K77', 'R18')  then DIAG=1;
			end;
			if DIAG=1 ;
		%END;
	%ELSE
		%DO;
			do i=1 to 50;
			IF SUBSTR(_diag_code{i},1,4) in : ('B182') or SUBSTR(_diag_code{i}, 1,3) in ('C22','K70', 'K71', 'K72', 'K73', 'K74', 'K75', 'K76', 'K77', 'R18')  then DIAG=1;
			end;
			if DIAG=1 ;
		%END;
run;

 

If Year is part of the Test1 dataset, you could code the following:

data test;
	DROP	Nbr_of_Diag;
	set test1;
	array _diag_code (*) $ DIAG_CODE_: ;

	IF	Year	<=	2016	THEN
		Nbr_of_Diag	=	35;
	ELSE
		Nbr_of_Diag	=	50;

	do i=1 to Nbr_of_Diag;
	IF SUBSTR(_diag_code{i},1,4) in : ('B182') or SUBSTR(_diag_code{i}, 1,3) in ('C22','K70', 'K71', 'K72', 'K73', 'K74', 'K75', 'K76', 'K77', 'R18')  then DIAG=1;
	end;

	if DIAG=1 ;
run;

Jim

Baba9
Obsidian | Level 7
I would be using it this way does that make sense

%macro run_hmdb(yr=);

data hmdb&yr.;
set dss.Hmdb_dss_core_20&yr.;

format AGE_GRP $20.;
format PROVINCE $20.;
if analytical_inst_type_code in ('1','A') and strip(submitting_prov_code)
in ('4');
/*if upcase(admission_category) not in ('R') and
upcase(admission_category) not in ('S') and upcase(entry_code) not in ('S'
'N' );*/



/* general inclusion/exclusion */
if UPCASE(ENTRY_CODE) not in ( "S" "N") ;
if UPCASE(ADMISSION_CATEGORY) not in ("R" "S") ;


/*GENDER*/
if gender_code in ("F" , "M") then gender_include=1;
if gender_include=1;

/**AGE**/
if UPCASE(age_code) in ("D" ) and AGE_UNITS <=29 then delete;


/* AGE GROUPS */
if UPCASE(age_code) in ("Y" )and AGE_UNITS <30 then AGE_GRP = "Group 1: <30
yrs.";
else if UPCASE(age_code) in ("Y" )and 30 <= AGE_UNITS <= 49 then AGE_GRP =
"Group 2: 30-49 yrs.";
else if UPCASE(age_code) in ("Y" )and 50 <= AGE_UNITS <= 64 then AGE_GRP =
"Group 3: 50-64 yrs.";
else if UPCASE(age_code) in ("Y" )and AGE_UNITS >= 65 then AGE_GRP = "Group
4: >= 65 yrs.";
/*Acute IP*/
if ANALYTICAL_INST_TYPE_CODE in ("1") then inpatient = 1;
if inpatient = 1;

/**Diagnosis of interest HCV, CLD, or HCC **/

array _diag_code (*)$ DIAG_CODE_: ;
%If &yr. <= 2016 %Then
%Do

do i=1 to 35;
IF SUBSTR(_diag_code{i},1,4) in : ('B182') or SUBSTR(_diag_code{i}, 1,3)
in ('C22','K70', 'K71', 'K72', 'K73', 'K74', 'K75', 'K76', 'K77', 'R18')
then DIAG=1;

end;

if DIAG=1 ;
%end;
%Else
%Do;

do i=1 to 50;
IF SUBSTR(_diag_code{i},1,4) in : ('B182') or SUBSTR(_diag_code{i}, 1,3)
in ('C22','K70', 'K71', 'K72', 'K73', 'K74', 'K75', 'K76', 'K77', 'R18')
then DIAG=1;

end;

if DIAG=1 ;
%end;

array _cci_code (*)$ interv_cci_code_:;
array _ooh (*)$ ooh_ind_:;
array _status(*)$ status_attribute_code_:;

%If &yr. <= 2016 %Then
%Do
do j=1 to 20;

IF _cci_code{j} in :('1OA85LAXXK','1OA85VCXXK','1OA85WLXXJ', '1OA85WLXXK')
and _ooh[j] = ' ' and
_status[j] ne 'A' then INTERV=1;

end;
%end;
%Else
%Do;

do j=1 to 35;

IF _cci_code{j} in :('1OA85LAXXK','1OA85VCXXK','1OA85WLXXJ', '1OA85WLXXK')
and _ooh[j] = ' ' and
_status[j] ne 'A' then INTERV=1;

%end;

if DIAG=1 and INTERV=1 THEN FLAG=1;

/* DEATHS */
if Discharge_disposition in ('07' '72' '73' '74') then flag_InHospDeath =
1;


%if &yr. <= 18 %then %do;if DISCHARGE_DISPOSITION in ("07") then
flag_InHospDeath = 1;%end;
%if &yr. >= 18 %then %do;if DISCHARGE_DISPOSITION in ("72" "73" "74") then
flag_InHospDeath = 1 ;%end;


/**/


keep
fiscal_year
dad_transaction_id
SUBMITTING_PROV_CODE
province
ENTRY_CODE
ADMISSION_CATEGORY
ANALYTICAL_INST_TYPE_CODE
gender_code
age_code
age_units

gender_include
AGE_GRP
inpatient
DISCHARGE_DISPOSITION
DIAG_CODE_:
interv_cci_code_:
ooh_ind_:
status_attribute_code_:
FLAG
DIAG
INTERV
flag_InHospDeath

;
run;

%mend;

%run_hmdb(yr=06);%run_hmdb(yr=07);%run_hmdb(yr=08);%run_hmdb(yr=09);%run_hmdb(yr=10);%run_hmdb(yr=11);%run_hmdb(yr=12);%run_hmdb(yr=13);%run_hmdb(yr=14);%run_hmdb(yr=15);%run_hmdb(yr=16);%run_hmdb(yr=17);%run_hmdb(yr=18);
%run_hmdb(yr=19);
ballardw
Super User

With this stated as part of your macro

set dss.Hmdb_dss_core_20&yr.;

That strongly implies you &yr is going to be a two digit value to make names like Hmdb_dss_core_2016 for example. Which

makes this

%If &yr. <= 2016 %Then

a serious problem.

Suggestion: make sure that your YR macro parameter is a 4 digit year then use

set dss.Hmdb_dss_core_&yr.

Your output data sets would also have 4 digit year names.

 

If you are using the Do i=1 to 50 to adjust for the number of elements in your array then instead of the "50" use dim(arrayname). The DIM function returns the number of elements in an array. So if you have a small change in the data you don't have to change code as it will match the number of elements defined in an array statement like

array _diag_code (*)$ DIAG_CODE_: ;

 

BTW since the variables already exist the $ in above array statement is redundant.

Baba9
Obsidian | Level 7
data yr06;                                                                                                                              

array ds (*) DIAG_CODE_1-DIAG_CODE_35;                                                                                                  

do i=1 to 35;                                                                                                                           

  ds(i)=i;                                                                                                                              

end;                                                                                                                                    

array os (*) OOH_IND_1-OOH_IND_35;                                                                                                      

do j=1 to 35;                                                                                                                           

  os(j)=j;                                                                                                                              

end;                                                                                                                                    

run;                                                                                                                                    

                                                                                                                                        

data yr07;                                                                                                                              

array ds (*) DIAG_CODE_1-DIAG_CODE_50;                                                                                                  

do i=1 to 50;                                                                                                                           

  ds(i)=i;                                                                                                                              

end;                                                                                                                                    

array os (*) OOH_IND_1-OOH_IND_50;                                                                                                      

do j=1 to 50;                                                                                                                           

  os(j)=j;                                                                                                                              

end;                                                                                                                                    

run;                                                                                                                                    

                                                                                                                                        

data yr08;                                                                                                                              

array ds (*) DIAG_CODE_1-DIAG_CODE_25;                                                                                                  

do i=1 to 25;                                                                                                                           

  ds(i)=i;                                                                                                                              

end;                                                                                                                                    

array os (*) OOH_IND_1-OOH_IND_25;                                                                                                      

do j=1 to 25;                                                                                                                           

  os(j)=j;                                                                                                                              

end;                                                                                                                                    

run;                                                                                                                                    

                                                                                                                                        

                                                                                                                                        

%macro test(yr);                                                                                                                        

                                                                                                                                        

data new;                                                                                                                               

  set yr&yr;                                                                                                                            

  array _diag_code (*)$ DIAG_CODE_: ;                                                                                                   

  do i=1 to dim(_diag_code);                                                                                                            

     put _diag_code(i)=;                                                                                                                

  end;                                                                                                                                  

  array _ooh (*)$ ooh_ind_:;                                                                                                            

  do j=1 to dim(_ooh);                                                                                                                  

    put _ooh(j)=;                                                                                                                       

  end;                                                                                                                                  

run;                                                                                                                                    

                                                                                                                                        

%mend;                                                                                                                                  

                                                                                                                                        

options mprint;                                                                                                                         

%test(06)                                                                                                                               

%test(07)                                                                                                                               

%test(08)

Hello would appreciate if you can advise how using the dim function i can ensure that all the elements in an array are looked at for all the years

jimbarbour
Meteorite | Level 14

Yes, I think that makes sense, but it's very hard to read your code.  When you post code, please use the below icon:

jimbarbour_0-1627575272949.png

 

Jim

Baba9
Obsidian | Level 7
Alternatively 
How do I correct the error below:

2933  /**HMDB  QC Records F2006/07 to F2019/20.**/
2934
2935
2936  %macro run_hmdb(yr=);
2937
2938  data hmdb&yr.;
2939  set dss.Hmdb_dss_core_20&yr.;
2940
2941  format AGE_GRP $20.;
2942  format PROVINCE $20.;
2943  if analytical_inst_type_code in ('1','A') and strip(submitting_prov_code) in ('4');
2944  /*if upcase(admission_category) not in  ('R') and upcase(admission_category) not in  ('S')
2944! and upcase(entry_code) not in ('S' 'N' );*/
2945
2946
2947
2948      /* general inclusion/exclusion */
2949      if UPCASE(ENTRY_CODE) not in ( "S"  "N") ;
2950      if UPCASE(ADMISSION_CATEGORY) not in ("R" "S") ;
2951
2952
2953  /*GENDER*/
2954  if gender_code  in ("F" , "M") then gender_include=1;
2955  if gender_include=1;
2956
2957  /**AGE**/
2958  if UPCASE(age_code) in ("D" ) and AGE_UNITS <=29 then delete;
2959
2960
2961  /* AGE GROUPS */
2962      if UPCASE(age_code) in ("Y" )and AGE_UNITS <30 then AGE_GRP = "Group 1: <30 yrs.";
2963      else if UPCASE(age_code) in ("Y" )and 30 <= AGE_UNITS <= 49 then AGE_GRP = "Group 2:
2963! 30-49 yrs.";
2964      else if UPCASE(age_code) in ("Y" )and 50 <= AGE_UNITS <= 64 then AGE_GRP = "Group 3:
2964! 50-64 yrs.";
2965      else if UPCASE(age_code) in ("Y" )and AGE_UNITS >= 65 then AGE_GRP = "Group 4: >= 65
2965! yrs.";
2966  /*Acute IP*/
2967  if ANALYTICAL_INST_TYPE_CODE in ("1") then inpatient = 1;
2968      if inpatient = 1;
2969
2970      /**Diagnosis of interest HCV, CLD, or HCC **/
2971      array _diag_code (*)$ DIAG_CODE_: ;
2972  %If &yr. <= 2016 %Then
2973  %Do
2974
2975  do i=1 to 35;
ERROR: Expected %TO not found in %DO statement.
ERROR: A dummy macro will be compiled.
2976  IF SUBSTR(_diag_code{i},1,4) in : ('B182') or SUBSTR(_diag_code{i}, 1,3)
2977  in ('C22','K70', 'K71', 'K72', 'K73', 'K74', 'K75', 'K76', 'K77', 'R18')
2978  then DIAG=1;
2979
2980  end;
2981
2982  if DIAG=1 ;
2983  %end;
2984  %Else
2985  %Do;
2986
2987  do i=1 to 50;
2988  IF SUBSTR(_diag_code{i},1,4) in : ('B182') or SUBSTR(_diag_code{i}, 1,3)
2989  in ('C22','K70', 'K71', 'K72', 'K73', 'K74', 'K75', 'K76', 'K77', 'R18')
2990  then DIAG=1;
2991
2992  end;
2993
2994  if DIAG=1 ;
2995  %end;
2996
2997  array _cci_code (*)$ interv_cci_code_:;
2998  array _ooh (*)$ ooh_ind_:;
2999  array _status(*)$ status_attribute_code_:;
3000
3001  %If &yr. <= 2016 %Then
3002  %Do
3003  do j=1 to 20;
ERROR: Expected %TO not found in %DO statement.
3004
3005  IF _cci_code{j} in :('1OA85LAXXK','1OA85VCXXK','1OA85WLXXJ', '1OA85WLXXK')
3006  and _ooh[j] = ' ' and
3007  _status[j] ne 'A' then INTERV=1;
3008
3009  end;
3010  %end;
3011  %Else
3012  %Do;
3013
3014  do j=1 to 35;
3015
3016  IF _cci_code{j} in :('1OA85LAXXK','1OA85VCXXK','1OA85WLXXJ', '1OA85WLXXK')
3017  and _ooh[j] = ' ' and
3018  _status[j] ne 'A' then INTERV=1;
3019
3020  %end;
3021
3022
3023
3024   if DIAG=1 and INTERV=1 THEN FLAG=1;
3025
3026      /* DEATHS */
3027      if Discharge_disposition in ('07'  '72' '73' '74') then flag_InHospDeath = 1;
3028
3029
3030      %if &yr. <= 18 %then %do;if DISCHARGE_DISPOSITION  in ("07") then flag_InHospDeath = 1;
3030! %end;
3031      %if &yr. >= 18 %then %do;if DISCHARGE_DISPOSITION in ("72" "73" "74") then
3031! flag_InHospDeath = 1 ;%end;
3032
3033
3034      /**/
3035
3036
3037  keep
3038  fiscal_year
3039  dad_transaction_id
3040  SUBMITTING_PROV_CODE
3041  province
3042  ENTRY_CODE
3043  ADMISSION_CATEGORY
3044  ANALYTICAL_INST_TYPE_CODE
3045  gender_code
3046  age_code
3047  age_units
3048
3049  gender_include
3050  AGE_GRP
3051  inpatient
3052  DISCHARGE_DISPOSITION
3053  DIAG_CODE_:
3054  interv_cci_code_:
3055  ooh_ind_:
3056  status_attribute_code_:
3057  FLAG
3058  DIAG
3059  INTERV
3060  flag_InHospDeath
3061
3062  ;
3063  run;
3064
3065  %mend;

3066  %run_hmdb(yr=15);
      -
      180
WARNING: Apparent invocation of macro RUN_HMDB not resolved.

ERROR 180-322: Statement is not valid or it is used out of proper order.

WARNING: Apparent invocation of macro RUN_HMDB not resolved.
3066                   %run_hmdb(yr=16);
                       -
                       180

ERROR 180-322: Statement is not valid or it is used out of proper order.

WARNING: Apparent invocation of macro RUN_HMDB not resolved.
3066                                    %run_hmdb(yr=17);
                                        -
                                        180

ERROR 180-322: Statement is not valid or it is used out of proper order.

WARNING: Apparent invocation of macro RUN_HMDB not resolved.
3066                                                     %run_hmdb(yr=18);
                                                         -
                                                         180

ERROR 180-322: Statement is not valid or it is used out of proper order.

WARNING: Apparent invocation of macro RUN_HMDB not resolved.
3067  %run_hmdb(yr=19);
      -
      180

ERROR 180-322: Statement is not valid or it is used out of proper order.

How would i correct the error above

Tom
Super User Tom
Super User

Make sure to end your macro %DO statement.  Without the ending semi-colon it thinks you are trying to code an iterative %DO with a index variable named DO.

I find it make much more sense to place the %DO in these cases on the same line as the %THEN or %ELSE.  It makes the code much easier to scan for humans.

You have left them out in more than one place.  In this one you also left out an END for one of the DO statement that the macro is generating.

Keeping track of missing ends is much easier if you treat the indentation of the macro code and the SAS code it is generating separate.  That way when you are scanning the SAS code it is easier to check if the block closing lines are indented at the same place as the lines that open the block.

  %if &yr. <= 2016 %then %do;
do j=1 to 20;
  IF _cci_code{j} in: ('1OA85LAXXK','1OA85VCXXK','1OA85WLXXJ','1OA85WLXXK')
    and _ooh[j] = ' '
    and  _status[j] ne 'A' then INTERV=1;
end;
  %end;
  %else %do;
do j=1 to 35;
  IF _cci_code{j} in: ('1OA85LAXXK','1OA85VCXXK','1OA85WLXXJ','1OA85WLXXK')
    and _ooh[j] = ' '
    and _status[j] ne 'A' then INTERV=1;
end;
  %end;

 But looking the difference between the two sets of SAS code being generated the only difference I see is the upper bound on the DO loop.  If the goal is to scan the whole array this is where DIM() function can help.  It should let you eliminate the macro logic.

Since you are referencing three arrays you might want to make sure J never gets too large for any of them.

You could also save some time by stopping when you finally set INTERV to 1.

do j=1 to min(dim(_ooh),dim(_status),dim(_cci_code)) while (interv ne 1);
  if _cci_code[j] in: ('1OA85LAXXK','1OA85VCXXK','1OA85WLXXJ','1OA85WLXXK')
    and _ooh[j] = ' '
    and _status[j] ne 'A' then INTERV=1;
end;

hackathon24-white-horiz.png

The 2025 SAS Hackathon Kicks Off on June 11!

Watch the live Hackathon Kickoff to get all the essential information about the SAS Hackathon—including how to join, how to participate, and expert tips for success.

YouTube LinkedIn

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 7 replies
  • 1553 views
  • 3 likes
  • 4 in conversation