SAS IML list of objects

342 views Asked by At

In SAS IML I would like to pass a variable number of matices of numeric and character types and different dimensions to a user defined module. This can be implemented by e.g. creating a list of objects and pass the list to the module. For instance in R such data type is just called "list". Similar functionality is implemented in matlab as cell list, and in C++ and Java by inheritance from an abstract class. Unfortunately can not find this in SAS IML documentation.

How can list of arbitrary objects be created in SAS IML?

Thanks a lot.

Alex


Rick, thank you for quick reply.

The idea with optional arguments is restricted in long-term, since I need to pass 2-or-more arguments, not 15-or-fewer.

Howevr the second idea inspired me for another workaroud.

Before calling the function I have list of matrix names

names = {A, B, C};

In a cycle I will create temporary datasets according to the names, and then pass the names to the function. Inside the function I will have all the datasets accessible. After call of the function I will delete them in a loop.

Hope this will not be computationally expensive, otherwise will have to resort to one of your ideas.

Thanks

1

There are 1 answers

0
Rick On

SAS/IML does not support lists of matrices.

However, here are two ideas that might help you with your task. The first is to define your module to take optional arguments. You can call the module with an arbitrary number of matrices and the module can detect (by using the ISSKIPPED function) how many matrices you sent in. See the article "Define functions with optional parameters.") This is what I would choose if I have 15 or fewer matrices.

Here is how to implement the first idea:

proc iml;
/* Soln 1: Use optional args; detect which args are skipped */
start MyMod(x1 ,  x2=,  x3=,  x4=,  x5=, 
            x6=,  x7=,  x8=,  x9=,  x10=,
            x11=, x12=, x13=, x14=, x15=);
   /* compute number of args (stop at first empty arg) */
   ArgList = "x1":"x15";
   d = j(1, ncol(ArgList), 0); /* initialize to 0 */
   /* count args  */
   do i = 1 to ncol(ArgList);
      if ^IsSkipped(ArgList[i]) then do;
         var = value( ArgList[i] );
         d[i] = prod(dimension(var));
      end;
   end;
   d = remove(d, loc(d=0)); /* remove empty elements */
   print "The args are " (argList[1:ncol(d)]);
finish;

Test the module by passing in three arguments of different sizes:

A = {1 2, 3 4};
B = {1 2 3, 4 5 6};
C = I(4);
run MyMod(A, B, C);

The second idea is to pack your numerical matrices into a large single matrix where the i_th row contains the values of the i_th matrix. This will support arbitrarily many matrices, but it is somewhat wasteful in terms of memory. First you need to figure out the maximum number of elements in the union of the matrices. Then allocate a matrix big enough to hold all the matrices. The VALUE function (see the article "Indirect assignment") will be helpful for automating this step:

/* Soln 2: If more then 15 args, pack values as row vectors into large 
   numerical matrix. Use missing values to pad small matrices */
names = {A, B, C};
dims = j(nrow(names), 2);
do i = 1 to nrow(names);
   dims[i,] = dimension(value(names[i]));
end;
maxDim = max(dims[,#]);

/* convert each matrix to row vector; pad with missing values */
pack = j(nrow(names), maxDim, .);
do i = 1 to nrow(names);
   v = rowvec(value(names[i]));
   pack[i, 1:ncol(v)] = v;
end;
print pack;

The PACK matrix contains all the numerical data. (Do something similar for character matrices.) You can then send the DIM and PACK matrices to a module. The module can use the SHAPE function to unpack the matrices into their original shapes. For example, the following module unpacks the original matrices and prints them:

start unpack(dim, pack);
   do i = 1 to nrow(dim);
      x = shape( pack[i,1:prod(dim[i,])], dim[i,1] );
      print i x;
   end;
finish;

run unpack(dims, pack);