[R] ipf function in R

GREGOR Brian J Brian.J.GREGOR at odot.state.or.us
Thu Mar 6 17:25:51 CET 2008


Chandra,

While I can't advise on how to use the ipf function in the cat package,
I can offer the following function that we use here to balance rebalance
arrays with new marginal totals.

#ipf.R
#Function to iteratively proportionally fit a multidimensional array
#IPF also known as Fratar method, Furness method, raking and two/three
dimensional balancing.
#This method of matrix balancing is multiplicative since the margin
factors (coefficients)
#are multiplied by the seed array to yield the balanced array. 
#Ben Stabler, benjamin.stabler at odot.state.or.us, 9.30.2003
#Brian Gregor, brian.j.gregor at odot.state.or.us, 2002

#inputs:
#1) margins_ - a list of margin values with each component equal to a
margin
#Example: row margins of 210 and 300, column margins of 140 and 370
#and third dimension margins of 170 and 340.  
#[[1]]     [,1] [,2] [,3]
#210, 300
#[[2]]
#140, 370
#[[3]]
#170, 340
#2) seedAry - a multi-dimensional array used as the seed for the IPF
#3) iteration counter (default to 100)
#4) closure criteria (default to 0.001)

#For more info on IPF see:
#Beckmann, R., Baggerly, K. and McKay, M. (1996). "Creating Synthetic
Baseline Populations."
#   Transportation Research 30A(6), 415-435.
#Inro. (1996). "Algorithms". EMME/2 User's Manual. Section 6.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~

ipf <- function(Margins_, seedAry, maxiter=100, closure=0.001) {
    #Check to see if the sum of each margin is equal
    MarginSums. <- unlist(lapply(Margins_, sum))
    if(any(MarginSums. != MarginSums.[1])) warning("sum of each margin
not equal")

    #Replace margin values of zero with 0.001
    Margins_ <- lapply(Margins_, function(x) {
          if(any(x == 0)) warning("zeros in marginsMtx replaced with
0.001") 
          x[x == 0] <- 0.001
          x
          })

    #Check to see if number of dimensions in seed array equals the
number of
    #margins specified in the marginsMtx
    numMargins <- length(dim(seedAry))
    if(length(Margins_) != numMargins) {
        stop("number of margins in marginsMtx not equal to number of
margins in seedAry")
    }

    #Set initial values
    resultAry <- seedAry
    iter <- 0
    marginChecks <- rep(1, numMargins)
    margins <- seq(1, numMargins)

    #Iteratively proportion margins until closure or iteration criteria
are met
    while((any(marginChecks > closure)) & (iter < maxiter)) {
        for(margin in margins) {
            marginTotal <- apply(resultAry, margin, sum)
            marginCoeff <- Margins_[[margin]]/marginTotal
            marginCoeff[is.infinite(marginCoeff)] <- 0
            resultAry <- sweep(resultAry, margin, marginCoeff, "*")
            marginChecks[margin] <- sum(abs(1 - marginCoeff))
        }    
        iter <- iter + 1
    }
    
    #If IPF stopped due to number of iterations then output info
    if(iter == maxiter) cat("IPF stopped due to number of iterations\n")

    #Return balanced array
    resultAry
}


Brian Gregor, P.E.
Transportation Planning Analysis Unit
Oregon Department of Transportation
Brian.J.GREGOR at odot.state.or.us
(503) 986-4120

> 
> Message: 143
> Date: Wed, 05 Mar 2008 18:14:28 +1100
> From: Chandra Shah <Chandra.Shah at Education.monash.edu.au>
> Subject: [R] ipf function in R
> To: r-help at r-project.org
> Message-ID: <47CE4854.2020103 at Education.monash.edu.au>
> Content-Type: text/plain; charset=ISO-8859-1; format=flowed
> 
> Hi
> I have a 3 x 2 contingency table:
> 10 20
> 30 40
> 50 60
> I want to update the frequencies to new marginal totals:
> 100 130
> 40 80 110
> I want to use  the ipf (iterative proportional fitting) 
> function which 
> is apparently in the cat package.
> Can somebody please advice me how to input this data and 
> invoke ipf in R 
> to obtain an updated contingency table?
> Thanks.
> By the way I am quite new to R.
> 
> -- 
>  
> 
> Dr Chandra Shah
> Senior Research Fellow
> Monash University-ACER Centre for the Economics of Education 
> and Training
> Faculty of Education, Building 6,
> Monash University
> Victoria
> Australia 3800
> Tel. +61 3 9905 2787
> Fax +61 3 9905 9184
> 
> www.education.monash.edu.au/centres/ceet
> 



More information about the R-help mailing list