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

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.


1 ACCEPTED SOLUTION

Accepted Solutions
ArtC
Rhodochrosite | Level 12

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

9 REPLIES 9
ballardw
Super User

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.

Doug
Calcite | Level 5

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

ArtC
Rhodochrosite | Level 12

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.

Doug
Calcite | Level 5

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.

Peter_C
Rhodochrosite | Level 12

Doug

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

ArtC
Rhodochrosite | Level 12

[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;

MikeZdeb
Rhodochrosite | Level 12

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

ArtC
Rhodochrosite | Level 12

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.

Peter_C
Rhodochrosite | Level 12

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? ;;

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

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
  • 9 replies
  • 1498 views
  • 7 likes
  • 5 in conversation