C++ routines to invoke a single iteration of the Iterative proportional updating (IPU) scheme. Targets and classes are assumed to be one dimensional in the ipf_step functions. combine_factors aggregates several vectors of type factor into a single one to allow multidimensional ipu-steps. See examples.

ipf_step_ref(w, classes, targets)

ipf_step(w, classes, targets)

ipf_step_f(w, classes, targets)

combine_factors(dat, targets)

Arguments

w

a numeric vector of weights. All entries should be positive.

classes

a factor variable. Must have the same length as w.

targets

key figure to target with the ipu scheme. A numeric verctor of the same length as levels(classes). This can also be a table produced by xtabs. See examples.

dat

a data.frame containing the factor variables to be combined.

Details

ipf_step returns the adjusted weights. ipf_step_ref does the same, but updates w by reference rather than returning. ipf_step_f returns a multiplicator: adjusted weights divided by unadjusted weights. combine_factors is designed to make ipf_step work with contingency tables produced by xtabs.

Examples

############# one-dimensional ipu ############## ## create random data nobs <- 10 classLabels <- letters[1:3] dat = data.frame( weight = exp(rnorm(nobs)), household = factor(sample(classLabels, nobs, replace = TRUE)) ) dat
#> weight household #> 1 0.6640834 c #> 2 5.1397911 b #> 3 1.2591308 a #> 4 0.6516811 c #> 5 0.9171716 b #> 6 2.1896192 a #> 7 0.4860760 c #> 8 3.0053915 c #> 9 5.6514550 a #> 10 0.5395121 c
## create targets (same lenght as classLabels!) targets <- 3:5 ## calculate weights new_weight <- ipf_step(dat$weight, dat$household, targets) cbind(dat, new_weight)
#> weight household new_weight #> 1 0.6640834 c 0.6210167 #> 2 5.1397911 b 3.3943026 #> 3 1.2591308 a 0.4150887 #> 4 0.6516811 c 0.6094186 #> 5 0.9171716 b 0.6056974 #> 6 2.1896192 a 0.7218362 #> 7 0.4860760 c 0.4545532 #> 8 3.0053915 c 2.8104875 #> 9 5.6514550 a 1.8630751 #> 10 0.5395121 c 0.5045239
## check solution xtabs(new_weight ~ dat$household)
#> dat$household #> a b c #> 3 4 5
## calculate weights "by reference" ipf_step_ref(dat$weight, dat$household, targets) dat
#> weight household #> 1 0.6210167 c #> 2 3.3943026 b #> 3 0.4150887 a #> 4 0.6094186 c #> 5 0.6056974 b #> 6 0.7218362 a #> 7 0.4545532 c #> 8 2.8104875 c #> 9 1.8630751 a #> 10 0.5045239 c
############# multidimensional ipu ############## ## load data factors <- c("time", "sex", "smoker", "day") tips <- data.frame(sex=c("Female","Male","Male"), day=c("Sun","Mon","Tue"), time=c("Dinner","Lunch","Lunch"), smoker=c("No","Yes","No")) tips <- tips[factors] ## combine factors con <- xtabs(~., tips) cf <- combine_factors(tips, con) cbind(tips, cf)[sample(nrow(tips), 10, replace = TRUE),]
#> time sex smoker day cf #> 1 Dinner Female No Sun 9 #> 2 Lunch Male Yes Mon 8 #> 2.1 Lunch Male Yes Mon 8 #> 3 Lunch Male No Tue 20 #> 2.2 Lunch Male Yes Mon 8 #> 1.1 Dinner Female No Sun 9 #> 2.3 Lunch Male Yes Mon 8 #> 1.2 Dinner Female No Sun 9 #> 3.1 Lunch Male No Tue 20 #> 2.4 Lunch Male Yes Mon 8
## adjust weights weight <- rnorm(nrow(tips)) + 5 adjusted_weight <- ipf_step(weight, cf, con) ## check outputs con2 <- xtabs(adjusted_weight ~ ., data = tips) sum((con - con2)^2)
#> [1] 0