Thanks Rick and Xia - There is a programming solution (http://www.demog.berkeley.edu/~eddieh/datafitting.html). It consists of iteratively adjusting the cells to equal to marginal totals (one dimension at a time: divide cells by current marginal total and multiply by target marginal total). Below is the description for a 2D and 3D problem. I also including the SAS Macro solution for the 2D problem. Can you help adjust it to work for the 3D problem? Description of 2D solution Step 1: Each row of seed cells was proportionally adjusted to equal the marginal row totals (specifically, each cell was divided by the actual sum of the row of cells, then multiplied by the marginal row total). Step 2: Each column of (already row-adjusted) cells was proportionally adjusted to equal the marginal column totals. This is the end of the first ‘Iteration’. Steps 3 and higher: The above steps were repeated until the selected level of convergence was reached SAS macro code for the 2D problem: /*** -*-mode:simple-sas-*- ************************************************************** DESCRIPTION: IPF2WAY rakes the data in dataset &DSIN. to the row and column controls contained in datasets &ROWCTRLDS. and &COLCTRLDS., respectively. It does so using the two-way rake also known as Iterative Proportional Fitting and the RAS algorithm. PROGRAMMERS: webb.sprague@ofm.wa.gov, inspired by Chuck Taylor at the US Census Bureau --- DATE STARTED: 2011-08-30 INPUT (DATASETS, NAMES, ETC): DSIN: Input dataset VAR: Variables to be raked ROWCTRLDS: Row control dataset ROWCTRLVAR: Row control variable (single variable: all controls are in one column) COLCTRLDS: Column control dataset COLCTRLVAR: Column control variables OUTPUT (DATASETS, NAMES, ETC): DSOUT: Output dataset **********************************************************************************/ %macro IPF2WAY(DSIN=,DSOUT=,ROWCTRLDS=,VAR=,ROWCTRLVAR=,COLCTRLDS=,COLCTRLVAR=); proc iml; /* tolerance at which to stop iterating -- half a person ... */ TOL=0.5; /* Read in data, row controls, and column controls. xxxVAR parameters control which columns get fed into the various matrices */ use &DSIN.; read ALL var {&VAR.} into MATRIX; use &ROWCTRLDS.; read ALL var {&ROWCTRLVAR.} into ROWCTRL; use &COLCTRLDS.; read current var {&COLCTRLVAR.} into COLCTRL; /* use _MATRIX for intermediate and final results, keep original in MATRIX */ _MATRIX = MATRIX; /* Main loop ... */ /* ...initialize DIFF to large value to force execution of do loop */ DIFF = 1000; /* ... loop until finished. */ do until (DIFF < TOL); _OLDMAT = _MATRIX; ROWPR = _MATRIX / _MATRIX[,+]; /* divide matrix row-wise by rowsum to get controlled proportions*/ _MATRIX = ROWCTRL # ROWPR; /* multiply controls by proportion to get numbers*/ COLPR = _MATRIX / _MATRIX[+,]; /* ditto with columns */ _MATRIX = COLCTRL # COLPR; DIFF = max(abs(_MATRIX - _OLDMAT)); /* check if want to end loop */ end; /* output to a new dataset (XXX need to retain key vars for merging but dont - see note.) */ create &DSOUT. from _MATRIX [colname={&VAR}]; append from _MATRIX; quit; %mend; Description of 3D solution First, just as in two-dimensional IPF, you will need all of the marginals (e.g. Age by Sex, Age by Race, and Sex by Race), and each marginal must sum to the same value. You must also be sure that the dimensions of the marginals are consistent (e.g. that the values for the age groups are consistent). Second, you will need a three-dimensional (e.g. Age by Sex by Race) seed. You will then perform steps that are very similar to the two-dimensional case... Step 1: Proportionally adjust each (two-dimensional) row of cells to equal the pre-determined totals of Marginal 1. Step 2: Proportionally adjust each column of cells to equal the pre-determined totals of Marginal 2. Steps 3: Proportionally adjust each slice of cells to equal the pre-determined totals of Marginal 3. This is the end of the first ‘Iteration’. Steps 4 and higher: Repeat the above steps until the desired level of convergence is reached.
... View more