Iterative Proportional Fitting

/****************************************************************/
/*          S A S   S A M P L E   L I B R A R Y                 */
/*                                                              */
/*    NAME: IPF                                                 */
/*   TITLE: Iterative Proportional Fitting                      */
/* PRODUCT: IML                                                 */
/*  SYSTEM: ALL                                                 */
/*    KEYS: MATRIX  SUGI6                                       */
/*   PROCS: IML                                                 */
/*    DATA:                                                     */
/*                                                              */
/* SUPPORT: WMS                         UPDATE: SEP2013         */
/*     REF:                                                     */
/*                                                              */
/****************************************************************/


proc iml;
mod={0.01 15};  /* Stopping criteria */
dim={3 8};      /* Marital status has 3 levels; age has 8 */

/* New marginal totals for age by marital status */
table={1412 0 0 ,
       1402 0 0 ,
       1174 276 0 ,
       0 1541 0 ,
       0 1681 0 ,
       0 1532 0 ,
       0 1662 0 ,
       0 5010 2634};

/* Marginal totals are known for both marital status and age */
config={1 2};

/* Use known distribution for initial values */
initab={1306 83 0 ,
        619 765 3 ,
        263 1194 9 ,
        173 1372 28 ,
        171 1393 51 ,
        159 1372 81 ,
        208 1350 108 ,
        1116 4100 2329};

call ipf(fit,status,dim,table,config,initab,mod);

c={' SINGLE' ' MARRIED' 'WIDOWED/DIVORCED'};
r={'15 - 19' '20 - 24' '25 - 29' '30 - 34' '35 - 39' '40 - 44'
   '45 - 49' '50 OR OVER'};
print initab[colname=c rowname=r format=8.0
             label='Known Distribution (Previous Year)'],
      fit[colname=c rowname=r format=8.2
          label='Adjusted Estimates (Current Year)'];