BookmarkSubscribeRSS Feed
TXHHS
Calcite | Level 5

I have a list of ranges, data looks like this:

Enteral Formulas and AdditivesB4100-B4162B4100B4162
Parenteral Solutions and SuppliesB4164-B5200B4164B5200
Nutrition Infusion Pumps and Supplies Not Otherwise ClassifiedB9002-B9999B9002B9999
Other Theraputic ProceduresC1052-C1062C1052C1062
Outpatient PPSC1713-C9899C1713C9899
Walking Aids and AttachmentsE0100-E0159E0100E0159
Sitz Bath/EquipmentE0160-E0162E0160E0162
Commode Chair and SuppliesE0163-E0175E0163E0175

 

I need to turn it into a list that includes all the values in between, single column, something like to include every value in every range:

B9002
B9003
B9004
B9005
C1052
C1053
C1054
C1055
C1056
C1057
C1058
C1059
C1060
C1061
C1062
E0100
E0101
E0102

 

My thought was create a list with all the values A0001-A9999, B0001-B9999, etc for every letter of the alphabet then compare it back to my range list and only keep those that fall within one of the ranges.  I was thinking a nested loop, the outside loop increments for the letter (runs 26 times), the inside loop increments for the numbers (runs 9999 times for each letter). I can figure out a loop to create the values 0001-9999 but I can't figure out how to increment the letter.

 

I've tried converting the letter to ascii, hex, octal, so I can increment it as a number,  can't get any of that to work (example below).  It runs but it's not doing anything useful with the letter..the result is the same with ascii, hex, and octal.

data Proc_List;

ltr = 'A';

put ltr $ascii3.;

do i = 1 to 9999 by 1;

Proc = cat(ltr, put(i, z4.)); /* values are 1, 2.25, 4, ..., 16, 20.25, 25 */

output;

end;

run;

 

Any ideas?

4 REPLIES 4
PaigeMiller
Diamond | Level 26

Why does your output show B9002 to B9005, and not any other values starting with B?

--
Paige Miller
Reeza
Super User

My first question is why?
If you're trying to merge with a different table you can make the condition dynamic to search between two strings?

 

Otherwise:

  1. Split your code from the number - get the start and end of the intervals
  2. Get the prefix for the codes
  3. Loop through the values and create the new code
  4. Output to a new line

 

data want;
set have;

start = input(compress(startCode, , 'kd'), 8.);  /*1*/
end = input(compress(endCode, , 'kd'), 8.);  /*1*/
prefix = substr(startCode, 1, 1); /*2*/

do i=start to end; /*3*/
code = catt(prefix, put(i, z4.));
output; /*4*/
end;

run;

@TXHHS wrote:

I have a list of ranges, data looks like this:

Enteral Formulas and Additives B4100-B4162 B4100 B4162
Parenteral Solutions and Supplies B4164-B5200 B4164 B5200
Nutrition Infusion Pumps and Supplies Not Otherwise Classified B9002-B9999 B9002 B9999
Other Theraputic Procedures C1052-C1062 C1052 C1062
Outpatient PPS C1713-C9899 C1713 C9899
Walking Aids and Attachments E0100-E0159 E0100 E0159
Sitz Bath/Equipment E0160-E0162 E0160 E0162
Commode Chair and Supplies E0163-E0175 E0163 E0175

 

I need to turn it into a list that includes all the values in between, single column, something like to include every value in every range:

B9002
B9003
B9004
B9005
C1052
C1053
C1054
C1055
C1056
C1057
C1058
C1059
C1060
C1061
C1062
E0100
E0101
E0102

 

My thought was create a list with all the values A0001-A9999, B0001-B9999, etc for every letter of the alphabet then compare it back to my range list and only keep those that fall within one of the ranges.  I was thinking a nested loop, the outside loop increments for the letter (runs 26 times), the inside loop increments for the numbers (runs 9999 times for each letter). I can figure out a loop to create the values 0001-9999 but I can't figure out how to increment the letter.

 

I've tried converting the letter to ascii, hex, octal, so I can increment it as a number,  can't get any of that to work (example below).  It runs but it's not doing anything useful with the letter..the result is the same with ascii, hex, and octal.

data Proc_List;

ltr = 'A';

put ltr $ascii3.;

do i = 1 to 9999 by 1;

Proc = cat(ltr, put(i, z4.)); /* values are 1, 2.25, 4, ..., 16, 20.25, 25 */

output;

end;

run;

 

Any ideas?


 

PGStats
Opal | Level 21

You could hack SAS name list generation feature :

 

data have;
length name $100 range $16;
input name & range;
datalines;
Enteral Formulas and Additives  B4100-B4162 B4100   B4162
Parenteral Solutions and Supplies   B4164-B5200 B4164   B5200
Nutrition Infusion Pumps and Supplies Not Otherwise Classified  B9002-B9009 B9002   B9009
Other Theraputic Procedures  C1052-C1062 C1052   C1062
Outpatient PPS  C1713-C1719 C1713   C1719
Walking Aids and Attachments    E0100-E0159 E0100   E0159
Sitz Bath/Equipment  E0160-E0162 E0160   E0162
Commode Chair and Supplies  E0163-E0175 E0163   E0175
;

filename arrays temp;
data _null_;
file arrays;
set have;
arrayName = cats("x", _n_);
str = catx(" ", "array", arrayName, "{*}", range, ";");
put str;
run;

data want(keep=name);
%include arrays;
array all _numeric_;
do i = 1 to dim(all);
    name = vname(all{i});
    output;
    end;
run;
PG
Tom
Super User Tom
Super User

Why?  All of the possible numeric suffixes in those ranges will include codes that are not valid HCPCS codes.

Just merge the list with a list of valid codes and pick the ones that fall between the two codes.

Let's assume the table you are showing is named HAVE and last two variables are named LOW and HIGH. So if your dictionary table of all valid codes is named HCPCS then just join them:

proc sql;
create table want as
select a.*,b.code
from have a
left join hcpcs b
on b.code between a.low and a.high
;
quit;

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

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
  • 4 replies
  • 1069 views
  • 3 likes
  • 5 in conversation