N维迭代比例拟合,用于python
项目描述
迭代比例拟合是一种用于许多不同领域(如经济学或社会科学)的算法,用于改变结果,使沿一个或多个维度的聚合与已知的边际(或沿这些相同维度的聚合)匹配。
该算法有 2 个版本:
numpy 版本,目前最快
pandas 版本,比 numpy 版本更慢但更易于使用
该算法识别输入变量类型并使用适当的版本来解决问题。要安装软件包:
点安装ipfn
pip install git+http://github.com/dirguis/ipfn@master
有关更多信息和示例,请访问:
如果要测试包,请克隆 repo 并从主文件夹中运行:
py.test –verbose –color=yes 测试/tests.py
该项目类似于可用于 R 的 ipfp 包,并且已运行测试以确保相同的结果。
- 输入变量:
原始:numpy darray 矩阵或数据帧来执行 ipfn。
聚合:numpy 数组或 darray 或 pandas 数据帧/系列的列表。聚合与边际相同。
- 当沿一个或多个轴聚合时,它们是我们想要沿一个或多个轴的目标值。
维度:如果使用 numpy 对象,则为整数列表列表,如果使用 pandas 对象,则为列名。
- 保留维度,我们沿着这些维度求和以获得相应的聚合。
收敛率:如果有很多聚合/边际,放宽收敛标准可能很有用。
最大迭代:整数。允许的最大迭代次数。
详细:整数 0、1 或 2。每个案例编号包括先前案例编号的输出。
0:返回更新的矩阵。
1:带有输出状态的标志(0 表示失败,1 表示成功)。
2:在所有步骤中具有迭代次数和收敛速度信息的数据帧。
rate_tolerance:浮点值。如果高于 0.0,如 0.001,则一旦 2 次连续迭代的 conv_rate 变量之间的差异低于该指定值,算法将停止。
使用 Numpy 的维基百科示例:
为了说明迭代比例拟合,维基百科在这里使用了一个示例
以下是使用 IPFN 解决的示例:
import numpy as np from ipfn import ipfn m = [[40, 30, 20, 10], [35, 50, 100, 75], [30, 80, 70, 120], [20, 30, 40, 50]] m = np.array(m) xip = np.array([150, 300, 400, 150]) xpj = np.array([200, 300, 400, 100]) aggregates = [xip, xpj] dimensions = [[0], [1]] IPF = ipfn.ipfn(m, aggregates, dimensions, convergence_rate=1e-6) m = IPF.iteration() print(m)
算法的 numpy 版本的示例:
请按照以下示例运行该软件包。ipfn.py 脚本中列出了除了下面列出的示例之外的其他几个示例。此示例取自http://www.demog.berkeley.edu/~eddieh/IPFDescription/AKDOLWDIPFTHREED.pdf
首先,让我们定义一个 N=3 维的矩阵,该矩阵的特定大小为 2*4*3,并用一些值填充该矩阵
from ipfn import ipfn import numpy as np import pandas as pd m = np.zeros((2,4,3)) m[0,0,0] = 1 m[0,0,1] = 2 m[0,0,2] = 1 m[0,1,0] = 3 m[0,1,1] = 5 m[0,1,2] = 5 m[0,2,0] = 6 m[0,2,1] = 2 m[0,2,2] = 2 m[0,3,0] = 1 m[0,3,1] = 7 m[0,3,2] = 2 m[1,0,0] = 5 m[1,0,1] = 4 m[1,0,2] = 2 m[1,1,0] = 5 m[1,1,1] = 5 m[1,1,2] = 5 m[1,2,0] = 3 m[1,2,1] = 8 m[1,2,2] = 7 m[1,3,0] = 2 m[1,3,1] = 7 m[1,3,2] = 6
现在,让我们定义一些边际:
xipp = np.array([52, 48]) xpjp = np.array([20, 30, 35, 15]) xppk = np.array([35, 40, 25]) xijp = np.array([[9, 17, 19, 7], [11, 13, 16, 8]]) xpjk = np.array([[7, 9, 4], [8, 12, 10], [15, 12, 8], [5, 7, 3]])
我用字母 p 来表示被求和的维度
对于这个具体的例子,它们都必须小于 N=3 维并且与列联表 m 的维数一致。例如,沿第一个维度的边缘将由 2 个元素组成。我们希望维度 2 和维度 3 的 m 中元素的总和等于边际:
m[0,:,:].sum() == xipp[0] m[1,:,:].sum() == xipp[1]
定义聚合列表和相应的维度列表,以指示算法对每个聚合求和的维度:
aggregates = [xipp, xpjp, xppk, xijp, xpjk] dimensions = [[0], [1], [2], [0, 1], [1, 2]]
最后,运行算法:
IPF = ipfn.ipfn(m, aggregates, dimensions) m = IPF.iteration() print(xijp[0,0]) print(m[0, 0, :].sum())
算法的熊猫版本示例:
以同样的方式,我们可以运行一个类似的例子,但是使用一个数据框:
from ipfn import ipfn
import numpy as np
import pandas as pd
m = np.array([1., 2., 1., 3., 5., 5., 6., 2., 2., 1., 7., 2.,
5., 4., 2., 5., 5., 5., 3., 8., 7., 2., 7., 6.], )
dma_l = [501, 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, 501,
502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502]
size_l = [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4,
1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4]
age_l = ['20-25','30-35','40-45',
'20-25','30-35','40-45',
'20-25','30-35','40-45',
'20-25','30-35','40-45',
'20-25','30-35','40-45',
'20-25','30-35','40-45',
'20-25','30-35','40-45',
'20-25','30-35','40-45']
df = pd.DataFrame()
df['dma'] = dma_l
df['size'] = size_l
df['age'] = age_l
df['total'] = m
xipp = df.groupby('dma')['total'].sum()
xpjp = df.groupby('size')['total'].sum()
xppk = df.groupby('age')['total'].sum()
xijp = df.groupby(['dma', 'size'])['total'].sum()
xpjk = df.groupby(['size', 'age'])['total'].sum()
# xppk = df.groupby('age')['total'].sum()
xipp.loc[501] = 52
xipp.loc[502] = 48
xpjp.loc[1] = 20
xpjp.loc[2] = 30
xpjp.loc[3] = 35
xpjp.loc[4] = 15
xppk.loc['20-25'] = 35
xppk.loc['30-35'] = 40
xppk.loc['40-45'] = 25
xijp.loc[501] = [9, 17, 19, 7]
xijp.loc[502] = [11, 13, 16, 8]
xpjk.loc[1] = [7, 9, 4]
xpjk.loc[2] = [8, 12, 10]
xpjk.loc[3] = [15, 12, 8]
xpjk.loc[4] = [5, 7, 3]
aggregates = [xipp, xpjp, xppk, xijp, xpjk]
dimensions = [['dma'], ['size'], ['age'], ['dma', 'size'], ['size', 'age']]
IPF = ipfn.ipfn(df, aggregates, dimensions)
df = IPF.iteration()
print(df)
print(df.groupby('size')['total'].sum(), xpjp)
添加注释:
要在程序中调用算法,请执行:
from ipfn import ipfn
项目详情
下载文件
下载适用于您平台的文件。如果您不确定要选择哪个,请了解有关安装包的更多信息。