Jedi SAS Tricks: FUNC(y) Formats

6

In the previous episode, we built our own custom SAS function - a masterful trick indeed. Gordon Keener, a developer here at SAS, responded exuberantly "You think that's cool? - try THIS!" and proceeded to demonstrate prodigious powers with the SAS by using a custom function in a custom informat to elegantly resolve a programming problem. And another episode of Jedi SAS Tricks was launched...

First, if you haven't experienced the joy of bringing order to chaotic data using your own custom formats and informats, an excellent place to start is with Jonas Bilenas' SGF paper titled "I Can Do That With PROC FORMAT". But Gordon was talking about a new (SAS9.3) capability - the ability create a custom format that performs a function on a value. And because we know how to build our own user-defined functions with PROC FCMP, can't we build a custom format leveraging a custom function? Yes, we can! So let's dive in. If you want to click along, download the code here and fire up your SAS session. Just FYI, the code includes segments we don't discuss here (like producing the data sets, etc.)

The problem:
Our data is read in from a raw text file. US data has temperatures recorded in °F, World data in °C. How can we compare these values? After reading it in, the original SAS data looks like this:
Listing of the two original data sets

First, we'll build custom functions to convert °F to °C and °C to °F:

proc fcmp outlib=sasuser.MyFunc.MyPack;
function c2f(Tc);
   return(((Tc*9)/5)+32);
endsub;
function f2c(Tf);
   return((5/9)*(Tf-32));
endsub;
run;

Next, we could use these functions to "enrich" the data, adding a temp_c variable to the US data and a temp_f variable to the World data:

options cmplib=sasuser.Myfunc;
data us_both;
   set us;
   Temp_c=f2c(temp_f);
run;
 
data world_both;
   set world;
   Temp_F=c2f(temp_c);
run;

Results:
Listing of the two modified data sets

But - wouldn't it be cool to just print our °F temperatures in °C without having to modify the data? For that, let's write a custom format using our temperature conversion functions and use it in PROC PRINT:

proc format;
  value   c2f (default=5) other=[c2f()]; 
  value   f2c (default=5) other=[f2c()]; 
run;
title 'Printing with Formats';
proc print data=us label noobs;
  label temp_f='Temp (°C)';
  format temp_f f2c5.1;
run;

Results:
Listing of the US data set with the Farenheit temperature column formatted to display as Celsius

Even more intriguing, as Gordon originally suggested, we could build custom informats based on our temperature conversion functions and use them to read the temperature data from the raw data file directly into the units we desired. We could have read the Fahrenheit data in as Celsius or vice-versa, right from the start. For example:

data US_F_and_C;
   input @1 Place $14. @19 Date date7. @15 Temp_f @15 Temp_c f2c3.;
   format date date9.;
   datalines;
Alaska        -80 23jan71
Colorado      -60 01jan79
Idaho         -60 18jan43
North Dakota  -60 15feb36
Wyoming       -63 09feb33
;
run;
 
data World_F_and_C;
   input @1 Place $14. @15 Date date7. @23 Temp_f c2f3. @23 Temp_c ;
   format date date9.;
   datalines;
Antarctica    21jul83 -89
Siberia       06feb33 -68
Greenland     09jan54 -66
Yukon         03feb47 -63
Alaska        23jan71 -67
;
run;

And the results:
Listing of the data sets produced by reading in the raw data using custom informats

And that's a wrap! Until next time, may the SAS be with you!
Mark

Share

About Author

SAS Jedi

Principal Technical Training Consultant

Mark Jordan (a.k.a. SAS Jedi) grew up in northeast Brazil as the son of Baptist missionaries. After 20 years as a US Navy submariner pursuing his passion for programming as a hobby, in 1994 he retired, turned his hobby into a dream job, and has been a SAS programmer ever since. Mark writes and teaches a broad spectrum of SAS programming classes, and his book, "Mastering the SAS® DS2 Procedure: Advanced Data Wrangling Techniques" is in its second edition. When he isn’t writing, teaching, or posting “Jedi SAS Tricks”, Mark enjoys playing with his grand and great-grandchildren, hanging out at the beach, and reading science fiction novels. His secret obsession is flying toys – kites, rockets, drones – and though he usually tries to convince Lori that they are for the grandkids, she isn't buying it. Mark lives in historic Williamsburg, VA with his wife, Lori, and Stella, their cat. To connect with Mark, check out his SAS Press Author page, follow him on Twitter @SASJedi or connect on Facebook or LinkedIn.

Related Posts

6 Comments

  1. hanks for the plug. Check out my SAS Press book, "The Power of PROC FORMAT" for more FORMAT/INFORMAT tricks. Maybe it is time for a new edition to include PROC FCMP.

  2. Pingback: Homepage

    • SAS Jedi

      Sure - check out the PROC FORMAT documentation for the VALUE statement under the topic "value-range-set(s)". It's specified in the "existing-format" section.
      Regards,
      Mark

  3. Charu Shankar
    Charu Shankar on

    Informats are my personal favourite to read in unusual data! Love your example, well thought out & well done!

Back to Top