BookmarkSubscribeRSS Feed

Data Step for Timeseries: Part 3, the FCMP Procedure and Related Functionality

Started ‎03-15-2024 by
Modified ‎03-15-2024 by
Views 201

 

The purpose of this post is to explain and demonstrate the usefulness of the SAS Function Compiler procedure (FCMP, BASE/SAS) and related functionality in the context of processing timeseries data. The FCMP procedure lets you create and store SAS functions and subroutines. The previous posts in this series explained the fundamental ideas of processing timeseries as arrays and introduced some tools, syntax and data that will reappear here. If you haven’t had a chance to read them, links are below.

 

https://communities.sas.com/t5/SAS-Communities-Library/Data-Step-for-Timeseries-part-1-Overview/ta-p...

 

https://communities.sas.com/t5/SAS-Communities-Library/Data-Step-for-Timeseries-part-2-BY-Group-Proc...

 

Functions and subroutines are useful for implementing blocks of code that can be reused. They are similar in purpose to SAS Macros. The difference between functions and subroutines can be confusing. Functions return a value based on input arguments, so they aren’t suited for array operations. However, functions are useful in pretty much any programming scenario, and they provide a straightforward introduction to the FCMP procedure.

 

Subroutines can return multiple values, in this context arrays, based on an input array. We’ll illustrate the usefulness of subroutines by converting some array processing code that was presented in the previous post into a compact, reusable block that can be stored and called during processing. The FCMP procedure functionality is available in both SAS 9 and SAS Viya. The final demonstration in this post shows how a subroutine can be compiled and then called in CAS using the TSMODEL procedure.

 

Demonstration 1, creating and using a custom function

 

SAS provides many pre-defined functions, and you’re probably already familiar with several focused on timeseries processing; HOLIDAY, INTNX and INTCK are some popular examples. Sooner or later, programmers will run into a situation where a function would be useful for accomplishing a programming task, but a predefined one doesn’t exist. We’ll start with a user defined function that converts prices denominated in British pounds (GBP) into dollars (USD) using a specified exchange rate.

 

First, we’ll need a pointer to a storage location for the custom function. The compile library or CMPLIB option specifies that new functions can be compiled to the WORK library in a table named TIMEFUNC.

 

options cmplib = work.timefnc;

 

The new function is created in this call to the FCMP procedure.

 

proc fcmp outlib=work.timefnc.fxfunc;
   function exchg_convert(pounds, rate);
      dollars = (rate)*pounds;
      return(dollars);
   endsub;
run;

 

  • The FCMP procedure statement specifies the output location using a three-level name. FXFUNC is the package name that will be used to store the function in the compile library.
  • The FUNCTION statement names the function, here EXCHG_CONVERT, and lists the required arguments. The listed arguments are place holder names for a value in GBP and an exchange RATE.
  • Data step like syntax creates the output value, DOLLARS as a function of the input arguments.
  • The RETURN statement lists the value to be returned by the function.
  • ENDSUB marks the end of function creation.

 

It’s useful to understand how functions are compiled and stored, and the portion of the TIMEFNC table shown confirms the execution of this process. A compile library can contain multiple packages that contain a variety of functions and subroutines.

 

01_cw_blog3_cmplibtbl-300x169.png

 

Select any image to see a larger version.
Mobile users: To view the images, select the "Full" version at the bottom of the page.

 

Now that the EXCHG_CONVERT function is ready for use, we’ll call it in a Data Step. Because the RATE argument will change over time, we’ve coded it using a MACRO variable to make the process of updating easier and less error prone.

 

%let gbprate=1.2;
 
data work.dollars;
   set work.items_in_GBP;
   format USD_price dollar10.2;
   USD_price=exchg_convert(GBP_price, &gbprate);
run;

 

The DOLLARS table contains the results of running the EXCHG_CONVERT function. Recall that a function returns a value. There are multiple values of USD_PRICE in the table, but these were generated line by line, or from a sequence of function calls, as the data step ran.

 

02_cw_blog3_funttable-260x300.png

 

 

Demonstration 2, creating and calling a subroutine in SAS 9

 

In the previous post in this series, a new array (feature) that flags the week that contains Easter Sunday was created for a project. Since it’s reasonable to expect that other projects with week interval data may also have an Easter effect, we’ll convert that syntax into to a reusable block of code using a subroutine. Subroutines can be created and called in both SAS 9 and SAS Viya. Since the syntax is not identical, we’ll focus on SAS 9 for this demonstration, and then cover the SAS Viya process in the next one.

 

*Bonus extra credit challenge; generalize the definition of the subroutine below so that it can create Easter based on common date interval (DAY, WEEK, MONTH or QUARTER) input arrays.

 

proc fcmp outlib=work.timefnc.evntfncs;
   subroutine Easter_evnt(DateID[*], easter[*], yr[*]);
   outargs easter, yr;
   actlen = DIM(DateID);
   do i = 1 to actlen;
      yr[i]=year(DateID[i]);
      easter[i] = (week(DateID[i])=week(holiday('EASTER', yr[i])));
   end;
   endsub;
run;

 

  • The FCMP procedure statement references the compile library created in the first demonstration. The new package name for this subroutine is EVNTFNCS.
  • The SUBROUTINE statement specifies the subroutine name, EASTER_EVNT. Placeholder names for required input and output arrays are listed.
  • The OUTARGS statement lists placeholder names for the output arrays that will be produced. This statement replaces the RETURN statement used in the function creation example above.
  • The DO block contains the array processing steps. This syntax will produce two new arrays, EASTER and YR using a date ID array as input. Pre-defined SAS functions, WEEK, YEAR and HOLIDAY, are used in the processing.

 

The previous post showed identical syntax in a SUBMIT block in the TSMODEL procedure. The syntax in the SUMIT block was local to that call of TSMODEL. This subroutine will be available to any SAS functionality that accommodates it.

 

In this example, we’ll call the subroutine in a the TIMEDATA procedure. Recall that this SAS 9 procedure is tuned for processing timeseries as arrays. In addition to Data Step and TIMEDATA, other SAS 9 functionality accommodates functions and subroutines created in the FCMP procedure. See the Base SAS Procedures Guide for more details on the FCMP procedure; https://support.sas.com/documentation/cdl/en/proc/65145/PDF/default/proc.pdf

 

proc timedata data=work.wineco_sorted outarray=winecoarrays
      print=(arrays);
   id date interval=week;
   by region type;
   var sales / accumulate=total;
   var baseprice promotion / accumulate=average;
   outarrays easter yr;
   call Easter_evnt(date, easter, yr);
   title "Create a feature for each BY group that flags Easter";
run;

 

  • The CALL statement references the EASTER_EVNT subroutine and produces two new arrays; EASTER and YR for each of the 16 BY groups in this level of the data.
  • Other TIMEDATA syntax is described in the first and second posts in this series.

 

The OUTARRAY table, WINECOARRAYS, contains an EASTER event variable. The portion shown below is for REGION1, Table Red (TBLRE) type wines.

 

03_cw_blog3_timedata_table.png

 

 

 Demonstration 3, creating and calling a subroutine in SAS Viya

 

Conceptually, this demonstration is the same as the previous one; subroutine syntax is created, compiled and then called to create the EASTER and YR arrays for the 16 BY groups in the WINECO data. Here, the data has been loaded into memory and the subroutine syntax will be compiled and called in a SUBMIT block in the TSMODEL procedure.

 

This demonstration follows a TSMODEL procedure documentation example. See: https://go.documentation.sas.com/doc/en/pgmsascdc/default/casforecast/casforecast_tsmodel_examples02...

 

First, the subroutine code is put into a SAS macro named FCMPCODE.

 

%macro fcmpcode;
   subroutine Easter_evnt(DateID[*], easter[*], yr[*]);
      outargs easter, yr;
      actlen = DIM(DateID);
      do i = 1 to actlen;
         yr[i]=year(DateID[i]);
         easter[i] = (week(DateID[i])=week(holiday('EASTER', yr[i])));
      end;
   endsub;
%mend;

 

Next, the EASTER_EVNT subroutine syntax is inserted into a TSMODEL procedure SUBMIT block with a call to the FCMPCODE Macro. Once the code is substituted in, it is compiled and then called within the submit block.

 

proc tsmodel data = mylib.wineco outarray=mylib.regtypeseries
      outsum=mylib.regtypesum;
   by region type;
   id date interval=week;
   var sales /acc = sum;
   var baseprice promotion/acc = avg;
   outarrays easter yr;
   submit;
      %fcmpcode;
      call Easter_evnt(date, Easter, yr);
   endsubmit;
run;

 

A portion of the OUTARRAY table REGTYPESERIES is shown below.

 

04_cw_blog3_timedata_table.png

 

The SAS Viya method for subroutine creation and compilation looks different from the FCMP procedure approach, but it preserves the primary advantages of custom subroutines for array processing.

 

This post was intended to be a basic introduction to the FCMP procedure and associated functionally in the context of processing timeseries arrays. Hopefully, you already have some ideas for custom subroutines and functions to create that will make your work easier and more efficient. Interested readers will find many more SAS FCMP examples online.

 

 

Find more articles from SAS Global Enablement and Learning here.

Version history
Last update:
‎03-15-2024 01:44 PM
Updated by:
Contributors

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

Register now!

Free course: Data Literacy Essentials

Data Literacy is for all, even absolute beginners. Jump on board with this free e-learning  and boost your career prospects.

Get Started

Article Tags