Functional Principal Component Analysis Action Set

FPCA Scoring with Underlying Sine and Cosine Eigenfunctions

This section contains PROC CAS code.

Note: Input data must be accessible in your CAS session, either as a CAS table or as a transient-scope table. A CAS table has a two-level name: the first level is your CAS engine libref, and the second level is the table name. You refer to this table in the CAS procedure by specifying only the second level. For more information about two-level names, see Chapter 2, Shared Concepts (SAS Viya: Machine Learning Procedures). A transient-scope table is called directly from the action and exists in memory for the duration of the action. For more information about accessing data, see SAS Viya: System Programming Guide. For more information about PROC CAS and programming in CASL, see SAS Cloud Analytic Services: CASL Programmer’s Guide and SAS Cloud Analytic Services: CASL Reference.

This example demonstrates how to train and score a functional principal component analysis (FPCA) model. First, you generate a simulated data set that contains sine and cosine eigenfunctions by using the IML procedure. Then you train an FPCA model by using the fPca action. Finally, you use the trained model to score a new data set by using the fPcaScore action.

The following steps use PROC IML to generate the simulated data, which will serve as input for the FPCA training and scoring actions:

proc iml;

   /* Set the random seed */
   call randseed(234);

   /* Number of subjects */
   N = 50;

   /* Number of measurements per subject */
   M = 100;

   /* Define the continuum, which equally spaces the sequence from 0 to 10 */
   s = do(0, 10, (10 - 0) / (M - 1));

   /* Define the mean function and eigenfunctions */
   start meanFunct(s);
      return (s + 10 # exp(-(s - 5)##2));
   finish;


   /* First eigenfunction */
   start eigFunct1(s);
      return (cos(2 * s * constant('PI') / 10) / sqrt(5));
   finish;

   /* Second eigenfunction */
   start eigFunct2(s);
      return (-sin(2 * s * constant('PI') / 10) / sqrt(5));
   finish;

   /* Create FPC scores */
   Ksi = j(N, 2);
   call randgen(Ksi, "Normal");

   /* Center and scale each column */
   Ksi = (Ksi - mean(Ksi)) / std(Ksi);   /* standardize */

   /* Scale scores */
   Ksi = Ksi * diag({5, 2});

   /* Compute response matrix */
   eig1 = eigFunct1(s);
   eig2 = eigFunct2(s);
   eigMat = eig1` || eig2`;

   meanVec = meanFunct(s); /* Row vector of length M */

   /* Compute y */
   y = Ksi * eigMat` + meanVec;

   /* Concatenate s and y horizontally */
   s_col = s`;
   s_y = s_col || y`;

   /* Create column names */
   y_colnames = "y1":"y50";
   colnames = {"_TIMEPOINTS_"} || y_colnames; /* Set s column name to _TIMEPOINTS_ */

   /* Save the concatenated data to a SAS data set in the Work library */
   create work.fpca_data from s_y[colname=colnames];
   append from s_y;
   close work.fpca_data;
quit;

Next, you load the generated fpca_data data set into a CAS table and use it to train an FPCA model. Then you score the same data set against the trained FPCA model.

%cassetup(libname=sascas1);
/* Create a copy of data set `fpca_data` in CAS library `sascas1`
   for both training and scoring */
data sascas1.fpca_train_data;
   set fpca_data;
run;

data sascas1.fpca_score_data;
   set fpca_data;
run;

/* Macro to generate the input list for the fPca action */
%macro generate_input_list;
   %do i = 1 %to 50;
      {name="y&i"} %if &i < 50 %then ,;
   %end;
%mend;

/* Start the CAS procedure */
proc cas;
   /* Load the FPCA action set into the CAS session */
   loadactionset "fpca";
   run;

   /* Perform FPCA training */
   action fPca result = r /
      /* Specify the input data set for FPCA */
      table = {name='fpca_train_data'},
      /* Output data set and number of components */
      output = {casout={name="SCORE_OF_TRAIN", replace=TRUE}, npc=4},
      /* Save eigenvectors */
      eigenVec = {name="EIGENVEC", replace=TRUE},
      /* Save eigenvalues */
      eigenVal = {name="EIGENVAL", replace=TRUE},
      /* Save the trained model state */
      saveState = {name="trainStore", replace=TRUE},
      /* List of input variables */
      input = {%generate_input_list};
   run;

   /* Print the results of the training action */
   print r;
quit;

The following code shows how to use the saved FPCA model to score a new data set by using the fPcaScore action:

proc cas;

   /* Load the FPCA action set into the CAS session */
   loadactionset "fpca";
   run;

   /* Perform FPCA scoring */
   action fPcaScore result = r /
      table = {name='fpca_score_data'},
      /* Input data set for scoring */

      output = {casout={name="SCORE_OF_TEST", replace=TRUE}, npc=4},
      /* Output scored data set and number of components */

      model = {name='trainStore'},
      /* Use the previously saved model state for scoring */

      input = {%generate_input_list};
      /* List of input variables */
   run;

   /* Print the results of the scoring action */
   print r;
quit;

The output CAS table SCORE_OF_TEST contains functional principal component score values that you derive from the scoring data by using the FPCA scoring process. It provides a reduced-dimensional representation that captures how the new observations align with the primary patterns from the training analysis, supporting downstream tasks such as anomaly detection, classification, and efficient data visualization.

FPCA Scoring with Underlying Sine and Cosine Eigenfunctions

This section contains Lua code for the analysis in the CASL version of this example, which contains details about the results.

For more information about coding in Lua, see Getting Started with SAS Viya for Lua and SAS Viya: System Programming Guide.

-- Connect to the CAS server to open a CAS session
local cas = require("cas")
local s = cas.new_session()

-- Load the FPCA action set
s:loadactionset{actionset = "fPca"}

-- Use a function to generate input variable names dynamically
local function generate_input_list(num_vars)
    local input_vars = {}
    for i = 1, num_vars do
        table.insert(input_vars, {name = "y" .. i})
    end
    return input_vars
end

-- Perform FPCA scoring
local result = s:fPcaScore{
    -- Input the data set for scoring
    table = {name = "fpca_score_data"},
    -- Output the scored data set
    output = {casout = {name = "SCORE_OF_TEST", replace = true}, npc = 4},
    -- Use a previously saved model state for scoring
    model = {name = "trainStore"},
    -- Generate the list of input variables (assuming 50)
    input = generate_input_list(50)
}

-- Print the FPCA scoring results
print(result)

-- Close the CAS session
s:terminate()

FPCA Scoring with Underlying Sine and Cosine Eigenfunctions

This section contains Python code for the analysis in the CASL version of this example, which contains details about the results.

For more information about coding in Python, see Getting Started with SAS Viya for Python and SAS Viya: System Programming Guide.

import swat

# Connect to the CAS server to open a CAS session
s = swat.CAS()

# Load the FPCA action set
s.loadactionset(actionset="fPca")

# Use a function to generate input variable names dynamically
def generate_input_list(num_vars):
    return [{"name": f"y{i}"} for i in range(1, num_vars + 1)]

# Perform FPCA scoring
result = s.fPcaScore(
    # Input the data set for scoring
    table={"name": "fpca_score_data"},
    # Output the scored data set
    output={"casout": {"name": "SCORE_OF_TEST", "replace": True}, "npc": 4},
    # Use a previously saved model state for scoring
    model={"name": "trainStore"},
    # Generate the list of input variables (assuming 50)
    input=generate_input_list(50)
)

# Print the FPCA scoring results
print(result)

# Close the CAS session
s.terminate()

FPCA Scoring with Underlying Sine and Cosine Eigenfunctions

This section contains R code for the analysis in the CASL version of this example, which contains details about the results.

For more information about coding in R, see Getting Started with SAS Viya for R and SAS Viya: System Programming Guide.

library('swat')

# Connect to the CAS server to open a CAS session
s <- CAS()

# Load the FPCA action set
loadActionSet(s, "fPca")

# Use a function to generate input variable names dynamically
generate_input_list <- function(num_vars) {
  lapply(1:num_vars, function(i) list(name = paste0("y", i)))
}

# Perform FPCA scoring
result <- cas.fPcaScore(
  s,
  # Input the data set for scoring
  table = list(name = "fpca_score_data"),
  # Output the scored data set
  output = list(casout = list(name = "SCORE_OF_TEST", replace = TRUE), npc = 4),
  # Use a previously saved model state for scoring
  model = list(name = "trainStore"),
  # Generate the list of input variables (assuming 50)
  input = generate_input_list(50)
)

# Print the FPCA scoring results
print(result)

# Close the CAS session
cas.shutdown(s)
Last updated: November 23, 2025