From: FRIENDLY@VM1.YORKU.CA (Michael Friendly)
Newsgroups: bit.listserv.sas-l
Subject: IML bug - MARG function
Date: 17 Nov 92 18:53:26 GMT
Reply-To: Michael Friendly <FRIENDLY@VM1.YORKU.CA>
Comments: Gated by NETNEWS@AUVM.AMERICAN.EDU

Below is a description of a bug in the SAS/IML function MARG (marginal
sums) that I reported to Tech Support, followed by SAS, SASLOG, and
LISTING files which demonstrate the problem, and show a work-around.

I'm copying this to SAS-L, since it demonstrates a useful technique
for reordering the dimensions of multidimensional tables in IML,
which explicitly handles only 2-way arrays.

- Michael

BUG:  The MARG function in SAS/IML does not accept negative values in
      the <table> argument.

Systems tested: 6.06/6.07 (VM/CMS), 6.07 (NeXT)

Description:  The SAS/IML documentation describes the conformability
      requirements for the arguments <dim>, and <table> only
      as:
          dim[#] = nrow(table)#ncol(table)
          dim[1:k][#] = ncol(table)   for some k,
      with no restrictions on the values in table.

      Although MARG was developed for frequency tables, it is also
      useful for:
       (a) finding marginal sums of *any* multidimensional table,

       (b) reordering the dimensions of a multidimensional table.
           This last use is particularly important since SAS/IML
           has no direct way to manipulate multidimensional arrays.

  Hence, the test for positive values in <table> should be removed.

Workaround:
  For a table with negative values, subtract the minimum value in
  the table before calling MARG, add it back to the result after.
+=============================================== Beginning of MARG SAS
title 'Demonstrate MARG bug';
proc iml;
   reset fw=6;
   table = { 1 2 3 4,
             5 6 7 8};
   dim = {2 2 2};

   *-- use marg to reorder the dimensions (turn table inside-out);
   order = {3,2,1};
   run marg(loc,newtab, dim,table,order);
   print 'Reordered table (positive values)', newtab;

   *-- marg chokes on values < 0 - this generates an error;
   dev = table - 5;
   run marg(loc,newtab, dim,dev  ,order);
   print newtab;

   *-- workaround: subtract min value, then add back in;
   mdev = min(dev);
   run marg(loc,newtab, dim,dev-mdev,order);
   print newtab;
   newtab = newtab + mdev;
   print 'Reordered (w/ negative values)', newtab;
quit;
-===================================================== End of MARG SAS
+============================================ Beginning of MARG SASLOG
11                                The SAS System 13:15 Tuesday, November 17, 199

 NOTE: Copyright(c) 1989 by SAS Institute Inc., Cary, NC USA.
 NOTE: SAS (r) Proprietary Software Release 6.07  TS301
       Licensed to YORK UNIVERSITY, Site 0007019005.

 NOTE: Running on IBM Model 4381 Serial Number 012441.


 1          proc iml;
 IML Ready
 2             reset fw=6;
 3             table = { 1 2 3 4,
 4                       5 6 7 8};
 5             dim = {2 2 2};
 6
 7             *-- use marg to reorder the dimensions (turn table inside-out);
 8             order = {3,2,1};
 9             run marg(loc,newtab, dim,table,order);
 10            print 'Reordered table (positive values)', newtab;
 11
 12            *-- marg chokes on values < 0;
 13            dev = table - 5;
 14            run marg(loc,newtab, dim,dev  ,order);
 ERROR: (execution) Invalid argument to function.
+ERROR: (execution) Invalid argument to function.
+ERROR: (execution) Invalid argument to function.

  operation : MARG     at line    14 column   4
  operands  : DIM, DEV, ORDER

 DIM           1 row       3 cols    (numeric)

       2      2      2

 DEV           2 rows      4 cols    (numeric)

      -4     -3     -2     -1
       0      1      2      3

 ORDER         3 rows      1 col     (numeric)

       3
       2
       1

  statement : RUN             at line    14 column   4
 15            print newtab;
 16
 17            *-- workaround: subtract min value, then add back in;
 18            mdev = min(dev);
 19            run marg(loc,newtab, dim,dev-mdev,order);
 20            print newtab;
 21            newtab = newtab + mdev;
 22            print 'Reordered (w/ negative values)', newtab;
 23         quit;
 Exiting IML.
 NOTE: The PROCEDURE IML printed page 1.

 ERROR: Errors printed on page 1.
+ERROR: Errors printed on page 1.
+ERROR: Errors printed on page 1.

12                                The SAS System 13:15 Tuesday, November 17, 199

 NOTE: SAS Institute Inc., SAS Campus Drive, Cary, NC USA 27513-2414
-================================================== End of MARG SASLOG
+=========================================== Beginning of MARG LISTING
1                                 The SAS System
                                                 13:15 Tuesday, November 17, 199

                        Reordered table (positive values)

             NEWTAB
                  1      5      3      7      2      6      4      8


             NEWTAB
                  1      5      3      7      2      6      4      8


             NEWTAB
                  0      4      2      6      1      5      3      7

                          Reordered (w/ negative values)

             NEWTAB
                 -4      0     -2      2     -3      1     -1      3

-================================================= End of MARG LISTING
Comments: Gated by NETNEWS@AUVM.AMERICAN.EDU