As the first step in the decommissioning of sasCommunity.org the site has been converted to read-only mode.


Here are some tips for How to share your SAS knowledge with your professional network.


Convert All Variables to Opposite Type

From sasCommunity
Jump to: navigation, search

The task is to create a successor to a SAS data set, replacing each character variable in the original with a numeric variable, and each numeric variable in the original with a character variable; this is not necessarily a useful thing to do. Here is a method which preserves variable order and variable attributes. First create a data set for the demonstration:

proc sql;
create table mixedtype 
 (   Month num
   , Year num
   , MeanTemp char(6) Label = 'Mean Temperature (Celsius)'
   , Rainfall char(6)  Label = 'Rainfall (Centimeters)'
 );
insert into mixedtype (Month, Year, MeanTemp, Rainfall)
 values (1, 2008, '5.5', '6.2')
 values (2, 2008, '6.4', '5.9')
 values (3, 2008, '9.8', '4.9')
 ;

Result:

                    Mean
                    Temperature  Rainfall
   Month      Year  (Celsius)    (Centimeters)
----------------------------------------------
       1      2008  5.5          6.2
       2      2008  6.4          5.9
       3      2008  9.8          4.9

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 catx (   ' ' 
                                , 'input ('
                                , name
                                , ', f32. ) as'
                                , name
                                , 'label ='
                                , quote( strip(label) )                               
                              )
        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:

left( put ( Month , best12. ) ) as Month label = ""
left( put ( Year , best12. ) ) as Year label = ""
input ( MeanTemp , f32. ) as MeanTemp label = "Mean Temperature (Celsius)"
input ( Rainfall , f32. ) as Rainfall label = "Rainfall (Centimeters)"

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 switchall as select &selections from mixedtype;
%symdel selections;

Result:

                                   Mean
                            Temperature       Rainfall
Month         Year            (Celsius)  (Centimeters)
------------------------------------------------------
1             2008                  5.5            6.2
2             2008                  6.4            5.9
3             2008                  9.8            4.9

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 ('SWITCHALL','MIXEDTYPE')
 order by varnum, memname desc;
quit;

Result:

                            Column
Column      Member       Number in  Column    Column  Column
Name        Name             Table  Type      Length  Format    Column Label
----------------------------------------------------------------------------------------------
Month       SWITCHALL            1  char          12
Month       MIXEDTYPE            1  num            8
Year        SWITCHALL            2  char          12
Year        MIXEDTYPE            2  num            8
MeanTemp    SWITCHALL            3  num            8            Mean Temperature (Celsius)
MeanTemp    MIXEDTYPE            3  char           6            Mean Temperature (Celsius)
Rainfall    SWITCHALL            4  num            8            Rainfall (Centimeters)
Rainfall    MIXEDTYPE            4  char           6            Rainfall (Centimeters)

This demonstrates that variable order and variable attributes are preserved.

Limitation: This technique will not produce correct results for variables requiring special informats (most notably, times and dates).

See also Convert Numeric Variables to Character and Convert Character Variables to Numeric.