ipfn: Iterative Proportional Fitting
raw JSON → 1.4.4 verified Fri May 01 auth: no python
ipfn is a Python library for iterative proportional fitting (IPF) with N dimensions. It is used to adjust contingency tables to match known marginal totals. The current version is 1.4.4. Release cadence is low; updates are infrequent.
pip install ipfn Common errors
error TypeError: cannot unpack non-iterable int object ↓
cause Passing a single integer as a marginal instead of an array.
fix
Wrap the integer in a numpy array: np.array([100])
error ValueError: operands could not be broadcast together with shapes ↓
cause Marginal dimensions do not match the original matrix dimensions.
fix
Check that each marginal array length matches the corresponding axis size of Z.
error ImportError: cannot import name 'ipfn' from 'ipfn' ↓
cause Old version of ipfn (before 1.0) used a different API.
fix
Upgrade to latest version: pip install --upgrade ipfn
Warnings
gotcha The `ipfn` function modifies the input array in-place. If you need to preserve the original matrix, pass a copy. ↓
fix Z_original = Z.copy() before calling ipfn.
gotcha Marginal totals must be provided as a list of numpy arrays, not as a single array or pandas Series. ↓
fix Ensure marginals = [array1, array2] with matching dimensions.
gotcha The library does not validate that marginal sums match the total sum of the input matrix. Discrepancies may cause divergence. ↓
fix Check that sum of each marginal equals sum of Z before fitting.
gotcha Convergence is not guaranteed; increase max_iteration or adjust convergence_rate if needed. ↓
fix Set max_iteration to a higher value (e.g., 1000) and convergence_rate to a looser tolerance (e.g., 1e-4).
Imports
- ipfn wrong
from ipfn import ipfn as ipfcorrectfrom ipfn import ipfn
Quickstart
import numpy as np
import pandas as pd
from ipfn import ipfn
# Seed marginal totals
marginals = [np.array([100, 200]), np.array([150, 150])]
# Original matrix
Z = np.array([[50, 50], [150, 50]])
# Create IPF object and fit
ipf = ipfn(Z, marginals, convergence_rate=1e-5, max_iteration=100)
ipf.iterate()
print(ipf.Z)