% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/ipf.r
\name{ipf}
\alias{ipf}
\title{Iterative Proportional Fitting}
\usage{
ipf(
  dat,
  hid = NULL,
  conP = NULL,
  conH = NULL,
  epsP = 1e-06,
  epsH = 0.01,
  verbose = FALSE,
  w = NULL,
  bound = 4,
  maxIter = 200,
  meanHH = TRUE,
  allPthenH = TRUE,
  returnNA = TRUE,
  looseH = FALSE,
  numericalWeighting = computeLinear,
  check_hh_vars = TRUE,
  conversion_messages = FALSE,
  nameCalibWeight = "calibWeight",
  minMaxTrim = NULL,
  print_every_n = 100
)
}
\arguments{
\item{dat}{a \code{data.table} containing household ids (optionally), base
weights (optionally), household and/or personal level variables (numerical
or categorical) that should be fitted.}

\item{hid}{name of the column containing the household-ids within \code{dat} or
NULL if such a variable does not exist.}

\item{conP}{list or (partly) named list defining the constraints on person
level.  The list elements are contingency tables in array representation
with dimnames corresponding to the names of the relevant calibration
variables in \code{dat}. If a numerical variable is to be calibrated, the
respective list element has to be named with the name of that numerical
variable. Otherwise the list element shoud NOT be named.}

\item{conH}{list or (partly) named list defining the constraints on
household level.  The list elements are contingency tables in array
representation with dimnames corresponding to the names of the relevant
calibration variables in \code{dat}. If a numerical variable is to be
calibrated, the respective list element has to be named with the name of
that numerical variable. Otherwise the list element shoud NOT be named.}

\item{epsP}{numeric value or list (of numeric values and/or arrays)
specifying the convergence limit(s) for \code{conP}. The list can contain
numeric values and/or arrays which must appear in the same order as the
corresponding constraints in \code{conP}. Also, an array must have the same
dimensions and dimnames as the corresponding constraint in \code{conP}.}

\item{epsH}{numeric value or list (of numeric values and/or arrays)
specifying the convergence limit(s) for \code{conH}. The list can contain
numeric values and/or arrays which must appear in the same order as the
corresponding constraints in \code{conH}. Also, an array must have the same
dimensions and dimnames as the corresponding constraint in \code{conH}.}

\item{verbose}{if TRUE, some progress information will be printed.}

\item{w}{name if the column containing the base weights within \code{dat} or NULL
if such a variable does not exist. In the latter case, every observation
in \code{dat} is assigned a starting weight of 1.}

\item{bound}{numeric value specifying the multiplier for determining the
weight trimming boundary if the change of the base weights should be
restricted, i.e. if the weights should stay between 1/\code{bound}*\code{w}
and \code{bound}*\code{w}.}

\item{maxIter}{numeric value specifying the maximum number of iterations
that should be performed.}

\item{meanHH}{if TRUE, every person in a household is assigned the mean of
the person weights corresponding to the household. If \code{"geometric"}, the
geometric mean is used rather than the arithmetic mean.}

\item{allPthenH}{if TRUE, all the person level calibration steps are
performed before the houshold level calibration steps (and \code{meanHH}, if
specified). If FALSE, the houshold level calibration steps (and \code{meanHH},
if specified) are performed after everey person level calibration step.
This can lead to better convergence properties in certain cases but also
means that the total number of calibration steps is increased.}

\item{returnNA}{if TRUE, the calibrated weight will be set to NA in case of
no convergence.}

\item{looseH}{if FALSE, the actual constraints \code{conH} are used for
calibrating all the hh weights. If TRUE, only the weights for which the
lower and upper thresholds defined by \code{conH} and \code{epsH} are exceeded are
calibrated. They are however not calibrated against the actual constraints
\code{conH} but against these lower and upper thresholds, i.e.
\code{conH}-\code{conH}*\code{epsH} and \code{conH}+\code{conH}*\code{epsH}.}

\item{numericalWeighting}{See \link{numericalWeighting}}

\item{check_hh_vars}{If \code{TRUE} check for non-unique values inside of a
household for variables in household constraints}

\item{conversion_messages}{show a message, if inputs need to be reformatted.
This can be useful for speed optimizations if ipf is called several times
with similar inputs (for example bootstrapping)}

\item{nameCalibWeight}{character defining the name of the variable for the
newly generated calibrated weight.}

\item{minMaxTrim}{numeric vector of length2, first element a minimum value
for weights to be trimmed to, second element a maximum value for weights to
be trimmed to.}

\item{print_every_n}{number of interation steps after which a summary table
is printed. The summary table shows all constraints which are not yet
reached according to \code{epsP} and \code{epsH}}
}
\value{
The function will return the input data \code{dat} with the calibrated
weights \code{calibWeight} as an additional column as well as attributes. If no
convergence has been reached in \code{maxIter} steps, and \code{returnNA} is \code{TRUE}
(the default), the column \code{calibWeights} will only consist of \code{NA}s. The
attributes of the table are attributes derived from the \code{data.table} class
as well as the following.
\tabular{ll}{
\code{converged} \tab Did the algorithm converge in \code{maxIter} steps? \cr
\code{iterations} \tab The number of iterations performed. \cr
\code{conP}, \code{conH}, \code{epsP}, \code{epsH} \tab See Arguments. \cr
\code{conP_adj}, \code{conH_adj} \tab Adjusted versions of \code{conP} and \code{conH} \cr
\code{formP}, \code{formH} \tab Formulas that were used to calculate \code{conP_adj} and
\code{conH_adj} based on the output table.
}
}
\description{
Adjust sampling weights to given totals based on household-level and/or
individual level constraints.
}
\details{
This function implements the weighting procedure described
here: \doi{10.17713/ajs.v45i3.120}.
Usage examples can be found in the corresponding vignette
(\code{vignette("ipf")}).

\code{conP} and \code{conH} are contingency tables, which can be created with \code{xtabs}.
The \code{dimnames} of those tables should match the names and levels of the
corresponding columns in \code{dat}.

\code{maxIter}, \code{epsP} and \code{epsH} are the stopping criteria. \code{epsP} and \code{epsH}
describe relative tolerances in the sense that
\deqn{1-epsP < \frac{w_{i+1}}{w_i} < 1+epsP}{1-epsP < w(i+1)/w(i) < 1+epsP}
will be used as convergence criterium. Here i is the iteration step and wi is
the weight of a specific person at step i.

The algorithm
performs best if all varables occuring in the constraints (\code{conP} and \code{conH})
as well as the household variable are coded as \code{factor}-columns in \code{dat}.
Otherwise, conversions will be necessary which can be monitored with the
\code{conversion_messages} argument. Setting \code{check_hh_vars} to \code{FALSE} can also
incease the performance of the scheme.
}
\examples{
\dontrun{

# load data
eusilc <- demo.eusilc(n = 1, prettyNames = TRUE)

# personal constraints
conP1 <- xtabs(pWeight ~ age, data = eusilc)
conP2 <- xtabs(pWeight ~ gender + region, data = eusilc)
conP3 <- xtabs(pWeight*eqIncome ~ gender, data = eusilc)

# household constraints
conH1 <- xtabs(pWeight ~ hsize + region, data = eusilc[!duplicated(hid)])

# simple usage ------------------------------------------

calibweights1 <- ipf(
  eusilc,
  conP = list(conP1, conP2, eqIncome = conP3),
  bound = NULL,
  verbose = TRUE
)

# compare personal weight with the calibweigth
calibweights1[, .(hid, pWeight, calibWeight)]

# advanced usage ----------------------------------------

# use an array of tolerances
epsH1 <- conH1
epsH1[1:4, ] <- 0.005
epsH1[5, ] <- 0.2

# create an initial weight for the calibration
eusilc[, regSamp := .N, by = region]
eusilc[, regPop := sum(pWeight), by = region]
eusilc[, baseWeight := regPop/regSamp]

calibweights2 <- ipf(
  eusilc,
  conP = list(conP1, conP2),
  conH = list(conH1),
  epsP = 1e-6,
  epsH = list(epsH1),
  bound = 4,
  w = "baseWeight",
  verbose = TRUE
)

# show an adjusted version of conP and the original
attr(calibweights2, "conP_adj")
attr(calibweights2, "conP")
}
}
\author{
Alexander Kowarik, Gregor de Cillia
}
