def ipfn_np(self, m, aggregates, dimensions, weight_col='<STR_LIT>'):
steps = len(aggregates)<EOL>dim = len(m.shape)<EOL>product_elem = []<EOL>tables = [m]<EOL>for inc in range(steps - <NUM_LIT:1>):<EOL><INDENT>tables.append(np.array(np.zeros(m.shape)))<EOL><DEDENT>original = copy.copy(m)<EOL>for inc in range(steps):<EOL><INDENT>if inc == (steps - <NUM_LIT:1>):<EOL><INDENT>table_update = m<EOL>table_current = tables[inc]<EOL><DEDENT>else:<EOL><INDENT>table_update = tables[inc + <NUM_LIT:1>]<EOL>table_current = tables[inc]<EOL><DEDENT>for dimension in dimensions[inc]:<EOL><INDENT>product_elem.append(range(m.shape[dimension]))<EOL><DEDENT>for item in product(*product_elem):<EOL><INDENT>idx = self.index_axis_elem(dim, dimensions[inc], item)<EOL>table_current_slice = table_current[idx]<EOL>mijk = table_current_slice.sum()<EOL>xijk = aggregates[inc]<EOL>xijk = xijk[item]<EOL>if mijk == <NUM_LIT:0>:<EOL><INDENT>table_update[idx] = table_current_slice<EOL><DEDENT>else:<EOL><INDENT>table_update[idx] = table_current_slice * <NUM_LIT:1.0> * xijk / mijk<EOL><DEDENT><DEDENT>product_elem = []<EOL><DEDENT>max_conv = <NUM_LIT:0><EOL>for inc in range(steps):<EOL><INDENT>for dimension in dimensions[inc]:<EOL><INDENT>product_elem.append(range(m.shape[dimension]))<EOL><DEDENT>for item in product(*product_elem):<EOL><INDENT>idx = self.index_axis_elem(dim, dimensions[inc], item)<EOL>ori_ijk = aggregates[inc][item]<EOL>m_slice = m[idx]<EOL>m_ijk = m_slice.sum()<EOL>if abs(m_ijk / ori_ijk - <NUM_LIT:1>) > max_conv:<EOL><INDENT>max_conv = abs(m_ijk / ori_ijk - <NUM_LIT:1>)<EOL><DEDENT><DEDENT>product_elem = []<EOL><DEDENT>return m, max_conv<EOL>
Runs the ipfn method from a matrix m, aggregates/marginals and the dimension(s) preserved.
For example:
from ipfn import ipfn
import numpy as np
m = np.array([[8., 4., 6., 7.], [3., 6., 5., 2.], [9., 11., 3., 1.]], )
xip = np.array([20., 18., 22.])
xpj = np.array([18., 16., 12., 14.])
aggregates = [xip, xpj]
dimensions = [[0], [1]]

IPF = ipfn(m, aggregates, dimensions)
m = IPF.iteration()