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-2024.png

Don't miss out on SAS Innovate - Register now for the FREE Livestream!

Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.

 

Register now!

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
  • 864 views
  • 0 likes
  • 3 in conversation