【问题标题】:How to effectively fit a set of numbers into a predetermined distribution如何有效地将一组数字拟合到预定分布中
【发布时间】:2019-06-22 23:52:39
【问题描述】:

假设我有一组数字,我想根据预先确定的分布将它们相加以适合同类群组。一个简单的例子是,如果一组数字的累积量为 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 以内,则显示为零 - 因为这似乎加快了该方法)。模拟的是从相应的彩色 sumproduct 计算的,理论只是概率乘以所有数字的总和。

我附上了下面的代码,但实际上这种方法并不有效,特别是如果我必须跨多个数据集执行此操作 - 这就是问题的现实。我希望能够将这个项目转移到像 R 这样的更高效的语言中(我有过这种经验——尽管程度不高),因为我相信它可以更快、更有效地完成这个过程?

我也知道我的算法存在缺陷,因为后来的一些同类群组不会像我们观察较小的数据集那样准确。它似乎在我不希望它做的总和产品中包含零(参见灰色列)。此外,我希望使用所有数字,有时会省略一个数字,因为它的包含意味着它离理论分布更远。我不确定如何执行上述操作,因此我很感激这方面的一些建议。

有人在R中做过这样的事情吗?

我也知道这可能是 Cross Validated 的一个问题 - 我真的不确定,所以请随意移动。我已在下面以文本形式附上了代码和表格。

提前致谢,

  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

【问题讨论】:

    标签: r


    【解决方案1】:

    使用 R,创建一些测试输入。然后使用贪心方法确定排序索引o。使用findInterval 确定断点b,然后创建一个分组向量并重新排列它以对应x 的原始顺序,以便x[i] 在组g[i] 中。请注意,split(x, g) 创建了一个 length(d) 组列表。

    # test input
    set.seed(123)
    x <- sample(20, 20)
    d <- c(.2, .3, .5) # assume in increasing order
    
    o <- order(x)
    b <- findInterval(cumsum(d) * sum(x), cumsum(x[o]))
    g <- rep(seq_along(d), diff(c(0, b)))[order(o)]
    
    # check distribution of result
    tapply(x, g, sum) / sum(x)
    ##         1         2         3 
    ## 0.1714286 0.3285714 0.5000000 
    

    【讨论】:

    • 我很欣赏这个答案,它在做我想做的大部分事情,但准确性有些偏差,因为高端的一些值通常相当大,一个选项是拆分这些大数字是否超过了某个阈值,但我很好奇您是否可以向我指出任何其他无需拆分即可解决此问题的算法。谢谢!
    • 谷歌设置分区.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-16
    • 1970-01-01
    • 1970-01-01
    • 2017-11-23
    相关资源
    最近更新 更多