The task is to create a successor to a SAS data set, replacing each numeric variable in the original with a character variable. Here is a method which preserves variable order and variable attributes. First create a data set for the demonstration:
proc sql; create table mixedtype as select name label = 'First Name' , sex format = $1. , age label = 'Age as of 1 March 2008' , height , weight format = 6.2 from sashelp.class;
Result:
Age as of 1 First March Name Sex 2008 Height Weight ----------------------------------------- Alfred M 14 69 112.50 Alice F 13 56.5 84.00 Barbara F 13 65.3 98.00 Carol F 14 62.8 102.50 Henry M 14 63.5 102.50 James M 12 57.3 83.00 Jane F 12 59.8 84.50 Janet F 15 62.5 112.50 Jeffrey M 13 62.5 84.00 John M 12 59 99.50 Joyce F 11 51.3 50.50 Judy F 14 64.3 90.00 Louise F 12 56.3 77.00 Mary F 15 66.5 112.00 Philip M 16 72 150.00 Robert M 12 64.8 128.00 Ronald M 15 67 133.00 Thomas M 11 57.5 85.00 William M 15 66.5 112.00
Next, this somewhat tricky query which uses DICTIONARY.COLUMNS as a source of metadata and creates the bulk of another query:
select case type when 'num' then catx ( ' ' , 'left( put (' , name , ',' , case when format is null then 'best12.' else format end , ') ) as' , name , 'label =' , quote( strip(label) ) ) when 'char' then name else catx ( ' ' , quote('Error on type') , 'as' , name ) end into : selections separated by ' , ' from dictionary.columns where libname='WORK' and memname='MIXEDTYPE';
To adapt for other tables change only the literals in the WHERE clause.
Result:
Name Sex left( put ( Age , best12. ) ) as Age label = "Age as of 1 March 2008" left( put ( Height , best12. ) ) as Height label = "" left( put ( Weight , 6.2 ) ) as Weight label = ""
The INTO clause takes these expressions and concatenates them into a comma-separated string which it stores in the macro variable SELECTIONS, which in turn is used in the statement which actually does the work:
create table allchar as select &selections from mixedtype; %symdel selections;
Result:
First Age as of 1 Name Sex March 2008 Height Weight ------------------------------------------------- Alfred M 14 69 112.50 Alice F 13 56.5 84.00 Barbara F 13 65.3 98.00 Carol F 14 62.8 102.50 Henry M 14 63.5 102.50 James M 12 57.3 83.00 Jane F 12 59.8 84.50 Janet F 15 62.5 112.50 Jeffrey M 13 62.5 84.00 John M 12 59 99.50 Joyce F 11 51.3 50.50 Judy F 14 64.3 90.00 Louise F 12 56.3 77.00 Mary F 15 66.5 112.00 Philip M 16 72 150.00 Robert M 12 64.8 128.00 Ronald M 15 67 133.00 Thomas M 11 57.5 85.00 William M 15 66.5 112.00
Another query against DICTIONARY.COLUMNS compares the attributes of the original and replacement variables:
select name format=$10. , memname format=$10. , varnum format=10. , type format=$8. , length format=6. , format format=$8. , label format=$30. from dictionary.columns where libname='WORK' and memname in ('ALLCHAR','MIXEDTYPE') order by varnum, memname desc; quit;
Result:
Column Column Member Number in Column Column Column Name Name Table Type Length Format Column Label -------------------------------------------------------------------------------------- Name MIXEDTYPE 1 char 8 First Name Name ALLCHAR 1 char 8 First Name Sex MIXEDTYPE 2 char 1 $1. Sex ALLCHAR 2 char 1 $1. Age MIXEDTYPE 3 num 8 Age as of 1 March 2008 Age ALLCHAR 3 char 12 Age as of 1 March 2008 Height MIXEDTYPE 4 num 8 Height ALLCHAR 4 char 12 Weight MIXEDTYPE 5 num 8 6.2 Weight ALLCHAR 5 char 6
This demonstrates that variable order and variable attributes are preserved.
Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!
Data Literacy is for all, even absolute beginners. Jump on board with this free e-learning and boost your career prospects.