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

Hi,

 

I am unsure if there is a limitation to proc format that I am not considering, but my proc format is only formatting part of the data.

 

Below is the macro I'm running in SAS 9.4: 

 

 

%macro readmit(indata, outdata);

proc format;
    value $&outdata._event_name_ readmission_1_arm_1='Readmit 1' readmission_2_arm_1='Readmit 2' readmission_3_arm_1='Readmit 3' 
		readmission_4_arm_1='Readmit 4' readmission_5_arm_1='Readmit 5' readmission_6_arm_1='Readmit 6' readmission_7_arm_1='Readmit 7' 
		readmission_8_arm_1='Readmit 8' readmission_9_arm_1='Readmit 9' readmission_10_arm_1='Readmit 10' readmission_11_arm_1='Readmit 11' 
		readmission_12_arm_1='Readmit 12' readmission_13_arm_1='Readmit 13' readmission_14_arm_1='Readmit 14' readmission_15_arm_1='Readmit 15' 
		readmission_16_arm_1='Readmit 16' readmission_17_arm_1='Readmit 17' readmission_18_arm_1='Readmit 18' readmission_19_arm_1='Readmit 19'
		readmission_20_arm_1='Readmit 20' readmission_21_arm_1='Readmit 21' readmission_22_arm_1='Readmit 22' readmission_23_arm_1='Readmit 23'
		readmission_24_arm_1='Readmit 24' readmission_25_arm_1='Readmit 25' readmission_26_arm_1='Readmit 26' readmission_27_arm_1='Readmit 27'
		readmission_28_arm_1='Readmit 28' readmission_29_arm_1='Readmit 29' readmission_30_arm_1='Readmit 30';
run;

data &outdata.;
	set &indata.;
	format &outdata._event_name &outdata._event_name_.;
	run;
%mend;

%readmit(readmissions, readmit);

 

 

While readmissions 1-20 (readmission_1_arm_1 - readmission_20_arm_1) are formatted correctly to Readmit 1 - Readmit 20, the formatting is not being applied to readmissions 21+ (readmission_21_arm_1 - readmission_30_arm_1). These later ones are formated as readmissio.

 

Thanks in advance!

1 ACCEPTED SOLUTION

Accepted Solutions
Reeza
Super User

There are some bugs in your code, I'm assuming you get errors when you run the code you posted because I did.

 

Note that you need a space in the PROC FORMAT. Also when you apply the format you need a $ in front of the format name. See the highlighted portions below.

 

This as posted, works for me. I created some fake data at the bottom that shows this. I would check your source data. My guess is your source data does not have the correct data. A quick way to check this, which you should always do in a recode, is to run a PROC FREQ and check the output. 

 

 

%macro readmit(indata, outdata);

proc format;
    value $ &outdata._event_name_ 
readmission_1_arm_1='Readmit 1' readmission_2_arm_1='Readmit 2' readmission_3_arm_1='Readmit 3' 
		readmission_4_arm_1='Readmit 4' readmission_5_arm_1='Readmit 5' readmission_6_arm_1='Readmit 6' readmission_7_arm_1='Readmit 7' 
		readmission_8_arm_1='Readmit 8' readmission_9_arm_1='Readmit 9' readmission_10_arm_1='Readmit 10' readmission_11_arm_1='Readmit 11' 
		readmission_12_arm_1='Readmit 12' readmission_13_arm_1='Readmit 13' readmission_14_arm_1='Readmit 14' readmission_15_arm_1='Readmit 15' 
		readmission_16_arm_1='Readmit 16' readmission_17_arm_1='Readmit 17' readmission_18_arm_1='Readmit 18' readmission_19_arm_1='Readmit 19'
		readmission_20_arm_1='Readmit 20' readmission_21_arm_1='Readmit 21' readmission_22_arm_1='Readmit 22' readmission_23_arm_1='Readmit 23'
		readmission_24_arm_1='Readmit 24' readmission_25_arm_1='Readmit 25' readmission_26_arm_1='Readmit 26' readmission_27_arm_1='Readmit 27'
		readmission_28_arm_1='Readmit 28' readmission_29_arm_1='Readmit 29' readmission_30_arm_1='Readmit 30';
run;

data &outdata.;
	set &indata.;
	format value $&outdata._event_name_.;
	run;
%mend;


*sample data;
data demo;
do i=1 to 30;
value = catt('readmission_', put(i, 8. -l), '_arm_1');
output;
end;
run;

*test; %readmit(demo, want);

How you would check this:

 

 

 

%macro readmit(indata, outdata);

proc format;
    value $ &outdata._event_name_ 
readmission_1_arm_1='Readmit 1' readmission_2_arm_1='Readmit 2' readmission_3_arm_1='Readmit 3' 
		readmission_4_arm_1='Readmit 4' readmission_5_arm_1='Readmit 5' readmission_6_arm_1='Readmit 6' readmission_7_arm_1='Readmit 7' 
		readmission_8_arm_1='Readmit 8' readmission_9_arm_1='Readmit 9' readmission_10_arm_1='Readmit 10' readmission_11_arm_1='Readmit 11' 
		readmission_12_arm_1='Readmit 12' readmission_13_arm_1='Readmit 13' readmission_14_arm_1='Readmit 14' readmission_15_arm_1='Readmit 15' 
		readmission_16_arm_1='Readmit 16' readmission_17_arm_1='Readmit 17' readmission_18_arm_1='Readmit 18' readmission_19_arm_1='Readmit 19'
		readmission_20_arm_1='Readmit 20' readmission_21_arm_1='Readmit 21' readmission_22_arm_1='Readmit 22' readmission_23_arm_1='Readmit 23'
		readmission_24_arm_1='Readmit 24' readmission_25_arm_1='Readmit 25' readmission_26_arm_1='Readmit 26' readmission_27_arm_1='Readmit 27'
		readmission_28_arm_1='Readmit 28' readmission_29_arm_1='Readmit 29' readmission_30_arm_1='Readmit 30';
run;

data &outdata.;
	set &indata.;
	recoded_var = put(value, $&outdata._event_name_.);
	run;

%*check recoding;

title 'Check recoding against original';
proc freq data=want;
table value*recoded_var /list;
run;
title;
%mend;



data demo;
do i=1 to 30;
value = catt('readmission_', put(i, 8. -l), '_arm_1');
output;
end;
run;



%readmit(demo, want);

And last but not least, this macro is overkill, since the number is in your data, you can replace this with a one line string function and scan. 

 

 

 

data demo;
	do i=1 to 30;
		value = catt('readmission_', put(i, 8. -l), '_arm_1');
		new_name = catx(" ", "Readmit", scan(value, 2, '_')); 
	output;
	end;
run;

@azz wrote:

Hi,

 

I am unsure if there is a limitation to proc format that I am not considering, but my proc format is only formatting part of the data.

 

Below is the macro I'm running in SAS 9.4: 

 

 

%macro readmit(indata, outdata);

proc format;
    value $&outdata._event_name_ readmission_1_arm_1='Readmit 1' readmission_2_arm_1='Readmit 2' readmission_3_arm_1='Readmit 3' 
		readmission_4_arm_1='Readmit 4' readmission_5_arm_1='Readmit 5' readmission_6_arm_1='Readmit 6' readmission_7_arm_1='Readmit 7' 
		readmission_8_arm_1='Readmit 8' readmission_9_arm_1='Readmit 9' readmission_10_arm_1='Readmit 10' readmission_11_arm_1='Readmit 11' 
		readmission_12_arm_1='Readmit 12' readmission_13_arm_1='Readmit 13' readmission_14_arm_1='Readmit 14' readmission_15_arm_1='Readmit 15' 
		readmission_16_arm_1='Readmit 16' readmission_17_arm_1='Readmit 17' readmission_18_arm_1='Readmit 18' readmission_19_arm_1='Readmit 19'
		readmission_20_arm_1='Readmit 20' readmission_21_arm_1='Readmit 21' readmission_22_arm_1='Readmit 22' readmission_23_arm_1='Readmit 23'
		readmission_24_arm_1='Readmit 24' readmission_25_arm_1='Readmit 25' readmission_26_arm_1='Readmit 26' readmission_27_arm_1='Readmit 27'
		readmission_28_arm_1='Readmit 28' readmission_29_arm_1='Readmit 29' readmission_30_arm_1='Readmit 30';
run;

data &outdata.;
	set &indata.;
	format &outdata._event_name &outdata._event_name_.;
	run;
%mend;

%readmit(readmissions, readmit);

 

 

While readmissions 1-20 (readmission_1_arm_1 - readmission_20_arm_1) are formatted correctly to Readmit 1 - Readmit 20, the formatting is not being applied to readmissions 21+ (readmission_21_arm_1 - readmission_30_arm_1). These later ones are formated as readmissio.

 

Thanks in advance!


 

 

View solution in original post

5 REPLIES 5
Reeza
Super User

There are some bugs in your code, I'm assuming you get errors when you run the code you posted because I did.

 

Note that you need a space in the PROC FORMAT. Also when you apply the format you need a $ in front of the format name. See the highlighted portions below.

 

This as posted, works for me. I created some fake data at the bottom that shows this. I would check your source data. My guess is your source data does not have the correct data. A quick way to check this, which you should always do in a recode, is to run a PROC FREQ and check the output. 

 

 

%macro readmit(indata, outdata);

proc format;
    value $ &outdata._event_name_ 
readmission_1_arm_1='Readmit 1' readmission_2_arm_1='Readmit 2' readmission_3_arm_1='Readmit 3' 
		readmission_4_arm_1='Readmit 4' readmission_5_arm_1='Readmit 5' readmission_6_arm_1='Readmit 6' readmission_7_arm_1='Readmit 7' 
		readmission_8_arm_1='Readmit 8' readmission_9_arm_1='Readmit 9' readmission_10_arm_1='Readmit 10' readmission_11_arm_1='Readmit 11' 
		readmission_12_arm_1='Readmit 12' readmission_13_arm_1='Readmit 13' readmission_14_arm_1='Readmit 14' readmission_15_arm_1='Readmit 15' 
		readmission_16_arm_1='Readmit 16' readmission_17_arm_1='Readmit 17' readmission_18_arm_1='Readmit 18' readmission_19_arm_1='Readmit 19'
		readmission_20_arm_1='Readmit 20' readmission_21_arm_1='Readmit 21' readmission_22_arm_1='Readmit 22' readmission_23_arm_1='Readmit 23'
		readmission_24_arm_1='Readmit 24' readmission_25_arm_1='Readmit 25' readmission_26_arm_1='Readmit 26' readmission_27_arm_1='Readmit 27'
		readmission_28_arm_1='Readmit 28' readmission_29_arm_1='Readmit 29' readmission_30_arm_1='Readmit 30';
run;

data &outdata.;
	set &indata.;
	format value $&outdata._event_name_.;
	run;
%mend;


*sample data;
data demo;
do i=1 to 30;
value = catt('readmission_', put(i, 8. -l), '_arm_1');
output;
end;
run;

*test; %readmit(demo, want);

How you would check this:

 

 

 

%macro readmit(indata, outdata);

proc format;
    value $ &outdata._event_name_ 
readmission_1_arm_1='Readmit 1' readmission_2_arm_1='Readmit 2' readmission_3_arm_1='Readmit 3' 
		readmission_4_arm_1='Readmit 4' readmission_5_arm_1='Readmit 5' readmission_6_arm_1='Readmit 6' readmission_7_arm_1='Readmit 7' 
		readmission_8_arm_1='Readmit 8' readmission_9_arm_1='Readmit 9' readmission_10_arm_1='Readmit 10' readmission_11_arm_1='Readmit 11' 
		readmission_12_arm_1='Readmit 12' readmission_13_arm_1='Readmit 13' readmission_14_arm_1='Readmit 14' readmission_15_arm_1='Readmit 15' 
		readmission_16_arm_1='Readmit 16' readmission_17_arm_1='Readmit 17' readmission_18_arm_1='Readmit 18' readmission_19_arm_1='Readmit 19'
		readmission_20_arm_1='Readmit 20' readmission_21_arm_1='Readmit 21' readmission_22_arm_1='Readmit 22' readmission_23_arm_1='Readmit 23'
		readmission_24_arm_1='Readmit 24' readmission_25_arm_1='Readmit 25' readmission_26_arm_1='Readmit 26' readmission_27_arm_1='Readmit 27'
		readmission_28_arm_1='Readmit 28' readmission_29_arm_1='Readmit 29' readmission_30_arm_1='Readmit 30';
run;

data &outdata.;
	set &indata.;
	recoded_var = put(value, $&outdata._event_name_.);
	run;

%*check recoding;

title 'Check recoding against original';
proc freq data=want;
table value*recoded_var /list;
run;
title;
%mend;



data demo;
do i=1 to 30;
value = catt('readmission_', put(i, 8. -l), '_arm_1');
output;
end;
run;



%readmit(demo, want);

And last but not least, this macro is overkill, since the number is in your data, you can replace this with a one line string function and scan. 

 

 

 

data demo;
	do i=1 to 30;
		value = catt('readmission_', put(i, 8. -l), '_arm_1');
		new_name = catx(" ", "Readmit", scan(value, 2, '_')); 
	output;
	end;
run;

@azz wrote:

Hi,

 

I am unsure if there is a limitation to proc format that I am not considering, but my proc format is only formatting part of the data.

 

Below is the macro I'm running in SAS 9.4: 

 

 

%macro readmit(indata, outdata);

proc format;
    value $&outdata._event_name_ readmission_1_arm_1='Readmit 1' readmission_2_arm_1='Readmit 2' readmission_3_arm_1='Readmit 3' 
		readmission_4_arm_1='Readmit 4' readmission_5_arm_1='Readmit 5' readmission_6_arm_1='Readmit 6' readmission_7_arm_1='Readmit 7' 
		readmission_8_arm_1='Readmit 8' readmission_9_arm_1='Readmit 9' readmission_10_arm_1='Readmit 10' readmission_11_arm_1='Readmit 11' 
		readmission_12_arm_1='Readmit 12' readmission_13_arm_1='Readmit 13' readmission_14_arm_1='Readmit 14' readmission_15_arm_1='Readmit 15' 
		readmission_16_arm_1='Readmit 16' readmission_17_arm_1='Readmit 17' readmission_18_arm_1='Readmit 18' readmission_19_arm_1='Readmit 19'
		readmission_20_arm_1='Readmit 20' readmission_21_arm_1='Readmit 21' readmission_22_arm_1='Readmit 22' readmission_23_arm_1='Readmit 23'
		readmission_24_arm_1='Readmit 24' readmission_25_arm_1='Readmit 25' readmission_26_arm_1='Readmit 26' readmission_27_arm_1='Readmit 27'
		readmission_28_arm_1='Readmit 28' readmission_29_arm_1='Readmit 29' readmission_30_arm_1='Readmit 30';
run;

data &outdata.;
	set &indata.;
	format &outdata._event_name &outdata._event_name_.;
	run;
%mend;

%readmit(readmissions, readmit);

 

 

While readmissions 1-20 (readmission_1_arm_1 - readmission_20_arm_1) are formatted correctly to Readmit 1 - Readmit 20, the formatting is not being applied to readmissions 21+ (readmission_21_arm_1 - readmission_30_arm_1). These later ones are formated as readmissio.

 

Thanks in advance!


 

 

azz
Calcite | Level 5 azz
Calcite | Level 5

Thanks Reeza! It looks like the second $ when applying the format was what caused the issue. I appreciate your suggestion for a cleaner string function. I'll definitely try to clean up the code a bit in this macro.

Tom
Super User Tom
Super User

@azz wrote:

Thanks Reeza! It looks like the second $ when applying the format was what caused the issue. I appreciate your suggestion for a cleaner string function. I'll definitely try to clean up the code a bit in this macro.


You must have had some other error.  SAS will silently add the $ for you.  If you accidentally leave the $ out of the format specification when attaching a format to a character variable in a FORMAT statement then SAS will look for a character format with the same base name as the numeric format your code used.  If it is found then there is no message, but if it is not found then you get an error message.

268    format y xyz. ;
                ----
                484
NOTE 484-185: Format $XYZ was not found or could not be loaded.

 

Reeza
Super User

@Tom The other error was in the format definition so the format never got created.

I highlighted that line in the code as well. 

Tom
Super User Tom
Super User

Check the values in your variable and make sure they match the values used in your format.  Including case and location of blanks or other invisible characters.

 

Also why aren't you using quotes around the character values in your format definition?

 

Why are you making multiple formats that have the exact same definition?  You can just make one format and attach that to multiple variables.

 

%macro readmit(indata, outdata);
proc format;
value $event_name
  'readmission_1_arm_1'='Readmit 1' 'readmission_2_arm_1'='Readmit 2'
  'readmission_3_arm_1'='Readmit 3' 'readmission_4_arm_1'='Readmit 4'
  'readmission_5_arm_1'='Readmit 5' 'readmission_6_arm_1'='Readmit 6'
  'readmission_7_arm_1'='Readmit 7' 'readmission_8_arm_1'='Readmit 8'
  'readmission_9_arm_1'='Readmit 9' 'readmission_10_arm_1'='Readmit 10'
  'readmission_11_arm_1'='Readmit 11' 'readmission_12_arm_1'='Readmit 12'
  'readmission_13_arm_1'='Readmit 13' 'readmission_14_arm_1'='Readmit 14'
  'readmission_15_arm_1'='Readmit 15' 'readmission_16_arm_1'='Readmit 16'
  'readmission_17_arm_1'='Readmit 17' 'readmission_18_arm_1'='Readmit 18'
  'readmission_19_arm_1'='Readmit 19' 'readmission_20_arm_1'='Readmit 20'
  'readmission_21_arm_1'='Readmit 21' 'readmission_22_arm_1'='Readmit 22'
  'readmission_23_arm_1'='Readmit 23' 'readmission_24_arm_1'='Readmit 24'
  'readmission_25_arm_1'='Readmit 25' 'readmission_26_arm_1'='Readmit 26'
  'readmission_27_arm_1'='Readmit 27' 'readmission_28_arm_1'='Readmit 28'
  'readmission_29_arm_1'='Readmit 29' 'readmission_30_arm_1'='Readmit 30'
;
run;

data &outdata.;
  set &indata.;
  format &outdata._event_name $event_name.;
run;
%mend readmit;

SAS Innovate 2025: Call for Content

Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 16. Read more here about why you should contribute and what is in it for you!

Submit your idea!

What is Bayesian Analysis?

Learn the difference between classical and Bayesian statistical approaches and see a few PROC examples to perform Bayesian analysis in this video.

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