We’re smarter together. Learn from this collection of community knowledge and add your expertise.

SAS Visual Forecasting 8.1 – Using Open Programming Interfaces

by Occasional Contributor Jack_Zhang on ‎08-03-2017 02:08 PM - edited on ‎10-26-2017 07:56 AM by Community Manager (1,684 Views)

SAS Viya™ is an open analytics platform that provides access to Cloud Analytic Services (CAS), a new and powerful engine for modern data analytics. SAS Visual Forecasting is available on the SAS Viya™ platform and it is accessible from SAS or other programming languages such as Python, R, Lua, and Java. Data scientists who do not know SAS programming can now leverage the power of SAS, and more specifically of SAS Visual Forecasting for their forecasting projects.  By doing so, they will get consistent and accurate forecast results faster, regardless of the programming language they are using. In this blog, I will provide an introduction to CAS sessions, action sets, actions, and an overview of SWAT (Scripting Wrapper for Analytics Transfer) package for Python.  I will also illustrate how you can use SWAT for Python to run CAS actions in Visual Forecasting through two code samples.


Overview of CAS Sessions, Action Sets and Actions


In SAS Viya™, a CAS client communicates with the CAS server to make a request through a CAS session.   The request is submitted as a CAS actionSet.action call, which is the only protocol through which a CAS client interacts with the CAS server.  CAS actions are aggregated into action sets that are based on specific functionality: they provide a rich and varied set of data management, analytical, and computational functionality.  In Visual Forecasting, two main CAS actions are used:

  • runTimeCode action, which is included in the timeData action set, the main engine that runs user-defined code for time series analysis and forecasting.
  • reconcileTwoLevels action, which is included in the tsreconcile action set, the utility function that performs a top-down reconciliation of the forecasted values that are generated at two different hierarchy levels.

For the current release of SAS Viya™, the CAS client programming support includes SAS, Python, R, Lua and Java. Using these languages, users can programmatically establish CAS sessions, load data into CAS tables, and run CAS actions to explore and process data on those CAS tables. When the heavy lifting on CAS has been completed, the resulting datasets can be further processed, analyzed, or visualized through the functionality available in the programming language itself.  For each programming language supported by CAS, there is a language-specific wrapper around CAS actions that enables the communication between the CAS client and the server. For example, for a SAS client, there are CAS-enabled procedures; and for a Python client, there is a wrapper package called SWAT for Python. The following table summarizes the available language-specific wrappers in Visual Forecasting 8.1. 



















* PROC CAS can invoke all CAS actions, including the two main actions in Visual Forecasting, with CASL statements.


Introduction to SAS SWAT Package for Python


SAS created a Python package to enable the integration between Python and CAS. The package is called SWAT (Scripting Wrapper for Analytics Transfer) for Python. It is

  • available for download from github.com/sassoftware
  • supported for Python 2.7, 3.4 or 3.5
  • required to have Python run on Linux 64-bit for better performance and
  • dependent on Pandas; importing SWAT will automatically load Pandas package.

The Pandas version should be 0.16.0 or greater for the SWAT package to function correctly. The SWAT package for Python allows you to program in Python, even when submitting actions to the CAS server.  You always start by creating a CAS connection object and loading the relevant CAS actions sets.  After that, the CAS actions are called as methods on the CAS connection object.    The parameters required by the CAS actions are supplied as Python keyword parameters. Any results that CAS actions generate are stored in a Python dictionary object.  The tabular results are automatically converted into a Pandas DataFrame. Essentially, all conversion to and from CAS objects is done behind scenes. You only have to program in Python. In addition to calling CAS actions and getting results back, much of the Pandas API is also mirrored in SWAT. This means that if you are familiar with Pandas, you should feel at home in SWAT. Now, here is a Python code sample that illustrate the usage of the SWAT package to run the runTimeCode action.


#import SWAT package
import swat

#connect to the CAS server and create a CAS session
s = swat.CAS(hostname="sascas01.race.sas.com", port=5570, 
             username="sastest1", password ="lnxsas")

#load the pricedata table into CAS, assuming pricedata.sashdat 
 is saved in the default caslib CASUSER
    casout={"caslib":'CASUSER', "name":'pricedata', "replace":True})

#create the code stream
do i=1 to _length_;
    if sale[i] ne . then do;
        relsale[i] = sale[i]/sbase;
    if price[i] ne . then do;

#load timeData action set

#run runTimeCode action


The timeData.runTimeCode action acquires time series data from an input table, runs a user-defined code stream on the time series identified by the groupBy groups, and saves the time series, the scalar result variables, and the object result instances to output tables. Its syntax is very comprehensive. For more information, please go to this link. When you invoke this runTimeCode action from a particular programming interface, you’ll need to do the following:

  • Ensure that a CAS server instance is up and running
  • Establish a CAS session for loading the input data table
  • Use the language-specific data type for setting the values of the parameters.

The user-defined code to be executed is contained in the string variable of the code parameter. Typically, it is a long string that consists of the Scripting Language statements provided in Visual Forecasting, that is, the statements included in submit; and endsubmit; block when using PROC TSMODEL. You may use language-specific macros or functions to dynamically generate the code, and make a macro or function call within the code parameter.


Using Python SWAT to Run CAS Actions in Visual Forecasting


The steps of using Python SWAT to run CAS actions in Visual Forecasting 8.1 are:

  • Import SWAT package
  • Create a CAS session
  • Load an input data table into CAS from a CAS library or from the Python client
  • Load required Action Sets
  • Invoke CAS actions to manipulate data in CAS tables and use Visual Forecasting packages
  • Close the CAS session.

Here is another sample Python code that illustrates the use of the ATSM package and the timeData.runTimeCode action to diagnose the time series at two different hierarchical. The code also calls the tsReconcile.reconcileTwoLevels action to reconcile the forecasts from the higher to lower level. In the current release of Visual Forecasting 8.1, the tsReconcile.reconcileTwoLevels action only supports top-down reconciliation. Bottom-up reconciliation can be achieved by aggregating the forecasted values through the runTimeCode action. Fully supported bottom-up and middle-out reconciliations will be added to a future release.


''' this script illustrates the use of ATSM package to diagnose 
    the time series at 2 different hierarchical levels and reconcile 
    the forecasts from higher level to lower level using 
    tsReconcile.reconcileTwoLevels action '''

#import SWAT package
import swat

#connect to the CAS server and create a CAS session
s = swat.CAS(hostname="sascas01.race.sas.com", port=5570, 
             username="sastest1", password ="lnxsas")

#load the pricedata table into CAS, assuming pricedata.sashdat 
 is saved in the default caslib CASUSER
    casout={"caslib":'CASUSER', "name":'pricedata', "replace":True})

#load timeData action set

#define the scripting language code for the timeData.runTimeCode action
        *declare ATSM objects;
        declare object dataFrame(TSDF);
        declare object diagnose(DIAGNOSE);
        declare object diagSpec(DIAGSPEC);
        declare object forecast(FORENG);
        declare object outFor(OUTFOR);
        declare object outEst(OUTEST);
        declare object outStat(OUTSTAT);

        *setup dependent and independent variables;
        rc = dataFrame.initialize();
        rc = dataFrame.addY(sale);
        rc = dataFrame.addX(price);

        *setup time sereis diagnose specifications;
        rc = diagSpec.open();
        rc = diagSpec.setArimax('identify', 'both');
        rc = diagSpec.setEsm('method', 'best');
        rc = diagSpec.close();

        *diagnose time sereis to generate candidate model list;
        rc = diagnose.initialize(dataFrame);
        rc = diagnose.setSpec(diagSpec);
        rc = diagnose.run();

        *run model selection and forecast;
        rc = forecast.initialize(diagnose);
        rc = forecast.setOption('lead', 12, 'holdoutpct', 0.1);
        rc = forecast.run();

        *collect forecast results;
        rc = outFor.collect(forecast);
        rc = outEst.collect(forecast);
        rc = outStat.collect(forecast);

#run timeData action for lower level data
   table={"name":"pricedata", "groupBy":{"regionName", 
                               "productLine", "productName"}},
   series= [{"name":"sale", "acc":"sum"}, {"name":"price", "acc":"avg"}],
   objOut=[{"objRef":"outFor", "table":{"name":"outFor_low", "replace":True}},
           {"objRef":"outEst", "table":{"name":"outEst_low", "replace":True}},
           {"objRef":"outStat", "table":{"name":"outStat_low", "replace":True}}],
   code = code)

#run timeData action for higher level data
   table={"name":"pricedata", "groupBy":{"regionName", "productLine"}},
   series= [{"name":"sale", "acc":"sum"}, {"name":"price", "acc":"avg"}],
   objOut=[{"objRef":"outFor", "table":{"name":"outFor_high", "replace":True}},
           {"objRef":"outEst", "table":{"name":"outEst_high", "replace":True}},
        {"objRef":"outStat", "table":{"name":"outStat_high", "replace":True}}],
   code = code)

#reconcile forecasts
s.tsReconcile.reconcileTwoLevels(casOut = {"name":"recfor", "replace": True},
    childTable = {"name":"outFor_low" , "groupBy":{"regionName", 
                                        "productLine", "productName"}},
    parentTable = {"name":"outFor_high"},
    timeid = "date")

#end the cas session

Note that the parameter values of the CAS action are set by using the Python dictionary object for table parameters or the Python list object for array parameters.  




You can access SAS Visual Forecasting 8.1 using several CAS client programming languages, such as SAS, Python, R, Lua, and Java.  Through the CAS actions, you first load data into CAS tables, then use the available SAS Visual Forecasting 8.1 actions to model and forecast the time series available in the input tables on the CAS server. One of the huge benefits of SAS Viya’s architecture is that you will get consistent results regardless of the language that you are using.


In next blog, I will feature some applications of SAS Visual Forecasting that further demonstrate the capabilities of this new and powerful forecasting solution from SAS.  


Relevant Blogs


SAS Visual Forecasting 8.1 – A New Scalable Efficient Flexible Forecasting Solution

  • Overview and background of SAS Visual Forecasting 8.1

SAS Visual Forecasting 8.1 – Data Manipulation with PROC TSMODEL

  • Overview of PROC TSMODEL from a data manipulation perspective

SAS Visual Forecasting 8.1 – Using Automatic Time Series Model (ATSM) Package

  • Overview of using ATSM objects for automatic time series modeling and forecasting
Your turn
Sign In!

Want to write an article? Sign in with your profile.

Looking for the Ask the Expert series? Find it in its new home: communities.sas.com/askexpert.