Help using Base SAS procedures

Dynamic Formats

Reply
N/A
Posts: 0

Dynamic Formats

Hello,

Lets say I have the variable "sifmt" which has the format values 4.1 , 5.1, 3.2, 7.2 etc for each lab test as below:

Test Sifmt
Albumin 4.1
Protein 5.1
WBC 6.2
........
.....
etc.

I am doing calculation with the format as below:
put(result*factor, 4.1) for Albumin and put(result*factor, 5.1) for Protien, etc. I don't want to use repetitive if conditions becuase these format values may change.

Any help would be appreciated !!!

Thanks,
/Sukanya
Super Contributor
Super Contributor
Posts: 3,174

Re: Dynamic Formats

Posted in reply to deleted_user
What result do you expect (and want) to see? Suggest you share what code you are executing to be a bit more specific here.

Scott Barry
SBBWorks, Inc.
Super User
Posts: 5,424

Re: Dynamic Formats

Posted in reply to deleted_user
I suggest that you create a macro that will dynamically generate the code (if-then/select/case), based on the values in your look-up table (with Test and Sifmt columns).

/Linus
Data never sleeps
Super Contributor
Posts: 474

Re: Dynamic Formats

Posted in reply to deleted_user
Hi.

Depending on the number of tests/formats, you could automate the format transformation by loading everything into one or two macro lists.
[pre]
proc sql noprint;
select TEST, SIFMT into :L_TESTS separated by ' ' , :L_TESTS_FMT separated by ' ' from TESTSLIST;
quit;

%put L_TESTS=&L_TESTS;
%put L_TESTS_FMT=&L_TESTS_FMT;
[/pre]
This will populate two macro vars (L_TEST and L_TESTS_FMT) each other with a list of elements (one with the test name, and the other with the corresponding format) separated by blanks.

Then you need to make a match when processing data with the corresponding test name to obtain its index position on the list. Then, the second list (the one with the formats) will hold at the same position the adequate format. Just pass it to the putn function, and its a done deal.

Something like this:
[pre]
data OUTDATA;
set INDATA;

* cycle through the list, match the test name and retrieve the element index;
IDX=0;
do until(scan("&L_TESTS",IDX) eq TEST or scan("&L_TESTS",IDX) eq '');
IDX+1;
end;
if scan("(&L_TESTS",IDX) eq '' then IDX=0; * test name not matched, IDX=0;

* apply automatically the correct format;
FINAL=putn(result*factor,scan(symget('L_TESTS_FMT'),IDX,' '));

run;
[/pre]
Completely automatic and not quite complex as it may seem.

Cheers from Portugal.

Daniel Santos @ www.cgd.pt
SAS Super FREQ
Posts: 8,864

Re: Dynamic Formats

Posted in reply to DanielSantos
Hi:
I don't believe you need fancy macro coding at all for this. The PUT function does not allow a variable or constant as the value of a format name. However, the PUTN function does. So you have to make a variable to hold the name of the format and then -use- that variable with the PUTN function, as shown in the program below.

Basically, the PUT statement:
[pre]
applyfmt = put(test,$appfmt.);
[/pre]

does the lookup and then the PUTN statement -uses- APPLYFMT to create the new variable:
[pre]
newval = putn(result*factor,applyfmt);
[/pre]

The entire program and results are below. I wasn't sure about the values for result and factor, so I just made up some numbers. Remember that when you assign the format size, that you must account for all the characters, numbers and punctuation in the size. So, this number 111.1 would be a size of 5.1, meaning 5 total characters with a decimal point and 1 character after the decimal. If you needed 11111.1, then the format would be 7.1 -- 7 total characters with a decimal point and 1 character after the decimal point.

cynthia
[pre]
** Program;
data testdata;
infile datalines;
input Test $ result factor;
return;
datalines;
Albumin 11 2
Protein 111 2
WBC 111 2
;
run;

proc format;
value $appfmt 'Albumin'= '4.1'
'Protein'= '5.1'
'WBC'= '6.2';
run;

data domult;
length newval $12;
set testdata;

** One approach -- use cascading IF statements or macro variables;

** Alternate approach -- associate the numeric format with particular TEST;
** Note -- use the PUTN function because it allows a variable to supply the name of a format;
applyfmt = put(test,$appfmt.);
newval = putn(result*factor,applyfmt);
run;

options nodate nonumber;
ods listing;
proc print data=domult;
title 'Using APPLYFMT to supply format value for PUTN';
run;

** Results;
Using APPLYFMT to supply format value for PUTN

Obs newval Test result factor applyfmt
1 22.0 Albumin 11 2 4.1
2 222.0 Protein 111 2 5.1
3 222.00 WBC 111 2 6.2
[/pre]
Super Contributor
Posts: 474

Re: Dynamic Formats

Posted in reply to Cynthia_sas
Cynthia, interesting approach.

I would stick with this one (easier to understand), unless the test/format list is quite extensive. In that case you could code the lookup format through the contents of a table, but then, everything gets more complex also.

Cheers from Portugal

Daniel Santos @ www.cgd.pt
N/A
Posts: 0

Re: Dynamic Formats

Posted in reply to DanielSantos
Thank you guys... It is working...

/SUkanya
Ask a Question
Discussion stats
  • 6 replies
  • 199 views
  • 0 likes
  • 5 in conversation