Help using Base SAS procedures

Format Creation

Accepted Solution Solved
Reply
Contributor
Posts: 53
Accepted Solution

Format Creation

I used the following macro to create a format lookup table:

  where the first parameter is the library, the second is the dataset name and the third is the text variable I want to convert to numeric with formatted values.

%create_numeric (work,vx,vxx);

The macro runs fine and the formats create just fine(a numeric format VXXA. and a character format $VXXAA.).

However, when I attempt to use the format it creates, I'm doing something wrong - I get all missing values:

Data VX2;

     set VX;

     newvar = input(put(vxx,$VXXAA.),best8.);

     format newvar vxxa.;

run;

Any suggestions? I used a similar procedure in other code successfully and cannot find the difference.



Accepted Solutions
Solution
‎08-11-2012 02:46 AM
Valued Guide
Posts: 634

Re: Format Creation

What I see is a double conversion using three formats.  Since we don't see your data I will guess that it looks something like:

proc format;
value $vxxaa
'a' = '1'
'b' = '2'
'c' = '3';
value vxx
1 = 10
2 = 20
3 = 30;
invalue vxxbb
'a' = 1
'b' = 2
'c' = 3;
run;

data have;
input vxx $;
newvar = input(put(vxx,$vxxaa.),best.);
altvar = input(vxx,vxxbb.);
put newvar= vxx.;
put altvar= altvar vxx.;
datalines;
a
b
c
run;

Notice here that the informat VXXBB can be used to simplify the INPUT/PUT combination.  We could simplify further if the variable NEWVAR could contain its formatted value.

As to your errors it may be because VXX is not initially character.

View solution in original post


All Replies
Super User
Posts: 11,343

Re: Format Creation

What are some values of the variable you are referencing as vxx and the formatted value?

Did you try extra paranthesis around the PUT function to force resolution? (Sometimes helps)

newvar = input((put(vxx,$vxxaa.)),best8.);

You might try making informats and using INPUTC and INPUTN instead.

Contributor
Posts: 53

Re: Format Creation

The values I am creating are fractions in the text format xx/xx from the original numeric values.

Solution
‎08-11-2012 02:46 AM
Valued Guide
Posts: 634

Re: Format Creation

What I see is a double conversion using three formats.  Since we don't see your data I will guess that it looks something like:

proc format;
value $vxxaa
'a' = '1'
'b' = '2'
'c' = '3';
value vxx
1 = 10
2 = 20
3 = 30;
invalue vxxbb
'a' = 1
'b' = 2
'c' = 3;
run;

data have;
input vxx $;
newvar = input(put(vxx,$vxxaa.),best.);
altvar = input(vxx,vxxbb.);
put newvar= vxx.;
put altvar= altvar vxx.;
datalines;
a
b
c
run;

Notice here that the informat VXXBB can be used to simplify the INPUT/PUT combination.  We could simplify further if the variable NEWVAR could contain its formatted value.

As to your errors it may be because VXX is not initially character.

Contributor
Posts: 53

Re: Format Creation

Art,

Yes this is is what I seek. The original values are converted to a character to accomodate a slash (/) in the final value..I then need to have the final numeric values (1,2,3, etc.) have the format applied to them which contains the slash.

Valued Guide
Posts: 2,177

Re: Format Creation

Doug

Have you looked to see if the FRACT format might help?

Valued Guide
Posts: 634

Re: Format Creation

[SAS 9.3]

Here is a format which uses an FCMP function to split the incoming string and calculate the fraction.  It also uses the FRACT. format to write the numeric result.  Notice one of the odd results of the FRACT format - something for me to look into.

options cmplib=work.functions;
proc fcmp outlib=work.functions.myfunc;
function nfract (f$) ;
   return(input(scan(f,1,'/'),best.)/input(scan(f,2,'/'),best.));
endsub;
run;
proc format;
invalue $readfrac
   other = [nfract()];
run;

* Show two ways to convert the value;

data have;
input cfract $8.  @1 xfract $readfrac8.;
put cfract= ;

put xfract;
nfract= nfract(cfract);
put nfract= nfract= fract10.;
datalines;
1/4
234/67
3/4
run;

Valued Guide
Posts: 765

Re: Format Creation

hi Art ... looks similar to ... Create an Informat from a User-Defined Function

http://www.sascommunity.org/wiki/Create_an_Informat_from_a_User-Defined_Function

Valued Guide
Posts: 634

Re: Format Creation

Mike, I would like to say that I did not know of your article on sasCommunity.org, but I know I did because I signed off on its associated sasCommunity.org tip http://www.sascommunity.org/wiki/Tips:Create_an_Informat_from_a_User-Defined_Function back in January. Hey that was 8 months ago...sigh  The solution in your sasCommunity article addresses a broader problem and is a bit more sophisticated than mine.  I suggest readers take a look at Mikes article for a better FCMP example.  Again the link to his article is http://www.sascommunity.org/wiki/Create_an_Informat_from_a_User-Defined_Function.

Folks, if you are new to PROC FCMP take a look at Mike's article and some of the others on sasCommunity.org.  The idea of using a function within a format [starting in SAS 9.3] is extremely powerful as it makes most DATA step functions (and user defined functions) available in procedure steps and wherever formats are used.

Valued Guide
Posts: 2,177

Re: Format Creation

Doug

Since you plan to convert (from character to numeric), perhaps your earlier successes had just an input() function on the right hand side of the expression, and applied a format to the resulting value.

Are you able to review your earlier,successful, code expressions?

From your initial definition of the requirement, I would have expected conversion to be:
   NumVar = input( charVar, ?? Informat. ) ;
and the re-presentation of the character version of the data would be achieved by just
assigning the format as the default for NumValue, like:
   Format numVar num2char. ;
Of course a macro implementation places & as often as needed in suitable places, but I
think it is important to get the central conversion clear first.

Having such a model you then set about creating the pair of formats:

/* for testing only .....
data your_data ;
set sashelp.class ;
CharVar=name ;
run;
*******end of testing only code *********/


Proc Sort data= your_data( keep= CharVar ) nodupkey
           Out= cntlin_data ;
    by charvar ;
Run ;

* now create cntlin data set ;
Data cntlin ;
   Retain fmtnameF
/* now here is a design policy decision
What naming convention do you adopt for the for pair of formats?
To keep it simple I'm suggesting reusing the name of the CharVar
However, formats are used globally in a SAS session and you may
need to convert the same variable name in different tables with different
sets of values for CharVar. The simple design is reliable only within a table.
Extending the simple to
     CharVar_tableName
combines two names each of which can be up to 32 wide, into a name that must be within 31 wide.

I expect you can adopt a suitable generic solution,
But for clarity of example, I ignore these issues.
******/
          inFmtName "CharVar"
          typeF 'N' intype 'I' hlo 'O' ;
   if 0 then set cntlin_data ;  * get attrib for CharVar ;
   CharVar= 'notFound' ;
   output ;
   hlo = ' ' ;  
   do NumVar = 1 by 1 while( not end_of_data ) ;
      set cntlin_data       end= end_of_data ;
      output ;
   end ;
   stop;
run ;

* each obs numbers the unique values of CharVar
and holds the required extras to build both format and informat ;;
proc format /* you might want to define a format catalog */
      cntlin = cntlin( rename= ( NumVar = start
                                 CharVar= label
                                fmtnameF= fmtname
                                   typeF= type ));
run ;
  
proc format /* now build  the informat from the same table */
      cntlin = cntlin( rename= ( NumVar = label
                                 CharVar= start
                               inFmtname= fmtname
                                 inType = type ));
run ;
************demo ;
;
%put >%sysfunc(   putn(      5, charvar ))< ;  *expect >Henry< ;
%put ?%sysfunc( inputn(  Henry, charvar ))? ;  *expect ?5?      ;
%put >%sysfunc(   putn(     -1, charvar ))< ;  *expect >notFound< ;
%put ?%sysfunc( inputn(unknown, charvar ))? ;  *expect ?.? ;
%put %sysfunc(  inputn(  Henry, charvar ), charvar); * Henry ;
%put ?%sysfunc(  putn( %sysfunc(inputn( unknown, charvar )), charvar ))?
     ;    *?notFound? ;;

🔒 This topic is solved and locked.

Need further help from the community? Please ask a new question.

Discussion stats
  • 9 replies
  • 549 views
  • 7 likes
  • 5 in conversation