说我有一组数字,我想根据预定的分布求和以适合队列。一个简单的示例是,如果一组数字的累积数量为100,而同类群组1,2和3的分布分别为0.2、0.3、0.5,那么我想找到一个数字子集,其总和为20,另一个总和为30的唯一子集和总和为50的最终唯一子集。显然,不必精确,只需将分布合理地匹配即可。
我在vba中有一种方法,可以利用求解器插件来找到最佳方法,以获取一组数字中的数字子集并接近(在3000内)预定的分布。这涉及使用具有二进制0,1约束的sumproduct和数字列表,然后找到该同类群组所需的总量与所描述的sumproduct之间的差。
完成此操作后,将删除此子集中的任何数字,然后使用缩小的子集执行求解器方法。我已经附上了过程演变的图像,我希望它是清晰的,颜色与迭代相对应。第一个(绿色)迭代具有完整列表,并且更改的变量是包含0/1的相应绿色列中的变量,以获得接近142,449.09
的和请注意,在此示例中,完整列表的总和为:1,424,490.85。
“差异”线是求解器目标,在每次迭代之后,目标是向右移一列。 (我已将其设置为如果差异在1000以内,则显示零-因为这似乎加快了方法的速度)。模拟是根据相应的有色和积计算得出的,而理论上只是将概率乘以所有数字的总和。
我已经附上了下面的代码,但实际上,此方法不是很有效,特别是如果我必须跨多个数据集执行此操作时-这是问题的现实。我希望能够将此项目转换为更高效的语言,例如R(我曾经使用过,尽管程度不高),因为我相信它可以更快,更有效地完成此过程?
我也意识到我的算法存在缺陷,因为后来的一些同类研究不如我们观察到较小的数据集那样准确。它似乎在总和积中包含零,而我不希望这样做(请参见灰色列)。我也想使用所有数字,有时会省略一个数字,因为它的包含意味着它离理论分布还很远。我不确定如何执行上述操作,因此希望在此方面提供一些建议。
有人在R中做过这样的事吗?
我也了解交叉验证可能是一个问题-我确实不确定是否可以随意移动。我已经在下面的文本形式中附加了代码和表格。
预先感谢
Sub solversimple()
Dim wb As Workbook
Dim ws As Worksheet
Dim rCell, rIter, rSum
Dim i as Integer
Set wb = Application.ThisWorkbook
Set ws = wb.Sheets("Output")
For i = 1 To 5
rCell = ws.Range("q8").Offset(0, i - 1).Address
rChange = ws.Range("h4:h36").Offset(0, i - 1).Address
rSum = ws.Range("I5:I39").Offset(0, i - 1).Address
solverreset
SolverOk SetCell:=rCell, MaxMinVal:=2, ValueOf:=0, ByChange:=rChange, _
Engine:=3, EngineDesc:="Evolutionary"
SolverAdd CellRef:=rChange, Relation:=5, FormulaText:="binary"
SolverAdd CellRef:=rSum, Relation:=5, FormulaText:="binary"
SolverSolve True
Next i
End Sub
Full List List after 1st It List after 2nd List after 3rd List after 4th 1 2 3 4 5
49000.21 49000.21 49000.21 49000.21 49000.21 0.00 0.00 0.00 0.00 1.00
51591.99 51591.99 51591.99 51591.99 51591.99 0.00 0.00 0.00 0.00 1.00
18390.18 18390.18 0.00 0.00 0.00 0.00 1.00 1.00 0.00 1.00
45490.39 45490.39 45490.39 45490.39 45490.39 0.00 0.00 0.00 0.00 1.00
37506.41 0.00 0.00 0.00 0.00 1.00 0.00 0.00 0.00 1.00
1460.11 1460.11 1460.11 0.00 0.00 0.00 0.00 1.00 1.00 0.00
136564.86 136564.86 136564.86 136564.86 0.00 0.00 0.00 0.00 1.00 1.00
41581.29 0.00 0.00 0.00 0.00 1.00 0.00 1.00 0.00 0.00
6138.26 6138.26 6138.26 0.00 0.00 0.00 0.00 1.00 0.00 0.00
23831.37 23831.37 23831.37 23831.37 0.00 0.00 0.00 0.00 1.00 1.00
4529.44 4529.44 0.00 0.00 0.00 0.00 1.00 1.00 1.00 1.00
1291.53 1291.53 1291.53 0.00 0.00 0.00 0.00 1.00 0.00 0.00
1084.88 1084.88 1084.88 0.00 0.00 0.00 0.00 1.00 0.00 0.00
33516.76 33516.76 0.00 0.00 0.00 0.00 1.00 0.00 1.00 0.00
43393.83 43393.83 0.00 0.00 0.00 0.00 1.00 1.00 0.00 0.00
81000.69 81000.69 81000.69 0.00 0.00 0.00 0.00 1.00 0.00 0.00
25397.64 25397.64 0.00 0.00 0.00 0.00 1.00 0.00 0.00 1.00
29473.54 29473.54 29473.54 0.00 0.00 0.00 0.00 1.00 1.00 1.00
39097.70 0.00 0.00 0.00 0.00 1.00 0.00 0.00 1.00 1.00
59669.99 59669.99 0.00 0.00 0.00 0.00 1.00 1.00 1.00 1.00
18639.97 18639.97 0.00 0.00 0.00 0.00 1.00 0.00 0.00 0.00
97198.13 97198.13 97198.13 0.00 0.00 0.00 0.00 1.00 0.00 1.00
5558.69 5558.69 0.00 0.00 0.00 0.00 1.00 1.00 1.00 0.00
16298.63 16298.63 0.00 0.00 0.00 0.00 1.00 0.00 1.00 1.00
67621.61 67621.61 67621.61 0.00 0.00 0.00 0.00 1.00 0.00 0.00
69388.09 69388.09 0.00 0.00 0.00 0.00 1.00 1.00 1.00 0.00
193524.89 193524.89 193524.89 193524.89 0.00 0.00 0.00 0.00 1.00 1.00
12455.61 0.00 0.00 0.00 0.00 1.00 1.00 0.00 0.00 1.00
7261.88 0.00 0.00 0.00 0.00 1.00 0.00 0.00 0.00 0.00
77879.68 77879.68 0.00 0.00 0.00 0.00 1.00 1.00 0.00 1.00
53891.97 53891.97 0.00 0.00 0.00 0.00 1.00 0.00 0.00 0.00
70602.68 70602.68 70602.68 70602.68 70602.68 0.00 0.00 0.00 0.00 1.00
4157.96 0.00 0.00 0.00 0.00 1.00 1.00 1.00 0.00 1.00
Cohort 1.00 2.00 3.00 4.00 5.00
Probability 0.10 0.30 0.20 0.25 0.15
Theoretical 142449.09 427347.26 284898.17 356122.71 213673.63
Simulated 142060.85 426554.86 285268.75 353921.12 216685.28
Difference 0.00 0.00 0.00 2201.59 3011.65
答案 0 :(得分:1)
使用R创建一些测试输入。然后使用贪婪方法确定排序索引o
。使用findInterval
确定断点b
,然后创建一个分组矢量并将其重新排列以对应于x
的原始顺序,以使x[i]
在{{1}组中}。请注意,g[i]
将创建一个split(x, g)
组列表。
length(d)