SAS - 选择最佳数量

时间:2015-06-29 18:35:05

标签: sas

我试图在SAS中解决问题,我在一系列群体中拥有大量客户,而我选择的数量需要尽可能在不同的类别中进行。用一张小桌子可以更容易解释,这是我试图解决的更大问题的简化。

这是表格:

Customer Category | Revenue band | Churn Band | # Customers

        A                 1             1              4895
        A                 1             2               383
        A                 1             3               222
        A                 2             1                28
        A                 2             2              2828
        A                 2             3               232
        B                 1             1              4454
        B                 1             2               545
        B                 1             3               454
        B                 2             1              4534
        B                 2             2               434
        B                 2             3               454

假设我需要从A类中选择3000个客户,从B类中选择3000个客户。从第二个类别,在每个A和B中,我需要从1和2中选择相等的数量。如果可能,我需要在每个1,2和3子类别中选择一个比例量。这个问题有优雅的解决方案吗?我对SAS比较陌生,到目前为止我已经调查了OPTMODEL,但这些例子要么太简单,要么太先进,不能对我有用。

编辑:我考虑过使用调查选择。我可以使用此选项在收入范围1,2和3中选择相同的大小。但是,如果我在个别流失频段中缺少客户,则surveyselect可能无法选择这些数字较低的最大客户数,我回去手动选择客户。

1 个答案:

答案 0 :(得分:0)

问题陈述中仍有一些含糊之处,但我希望下面的PROC OPTMODEL代码对你来说是一个好的开始。我尝试添加许多不同功能的示例,以便您可以随意使用模型,并希望更接近您实际需要的内容。

在您可以优化的众多内容中,我最大限度地减少了“如果可能”目标的最大违规行为,例如:

min MaxMismatch = MaxChurnMismatch;

我能够将您的约束建模为线性程序,这意味着它应该可以很好地扩展。您可能还有其他未提及的约束,但这可能超出了本网站的范围。

根据您发布的数据,您可以从print语句的输出中看到最优惩罚对应于从A,1,1中选择1500个客户,其中理想值为1736.这样更贵而忽略了几个群体的客户:

[1] ChooseByCat 
 A     3000 
 B     3000 

[1] [2] [3] Choose IdealProportion 
 A    1  1   1500      1736.670 
 A    1  2      0       135.882 
 A    1  3      0        78.762 
 A    2  1     28         9.934 
 A    2  2   1240      1003.330 
 A    2  3    232        82.310 
 B    1  1   1500      1580.210 
 B    1  2      0       193.358 
 B    1  3      0       161.072 
 B    2  1   1500      1608.593 
 B    2  2      0       153.976 
 B    2  3      0       161.072 

Proportion MaxChurnMisMatch 
  0.35478       236.67 

这可能不是理想的解决方案,但是如何确定如何准确建模您的要求对本网站来说并不那么有用。如果相关,您可以离线与我联系。

我在您的问题陈述中添加了引用,作为以下代码中的注释。

玩得开心!

data custCounts;
    input cat $ rev churn n;
datalines;
        A                 1             1              4895
        A                 1             2               383
        A                 1             3               222
        A                 2             1                28
        A                 2             2              2828
        A                 2             3               232
        B                 1             1              4454
        B                 1             2               545
        B                 1             3               454
        B                 2             1              4534
        B                 2             2               434
        B                 2             3               454
;

proc optmodel printlevel = 0;
    set CATxREVxCHURN init {} inter {<'A',1,1>};
    set CAT = setof{<c,r,ch> in CATxREVxCHURN} c; 

    num n{CATxREVxCHURN};
    read data custCounts into CATxREVxCHURN=[cat rev churn] n;
    put n[*]=;

    var Choose{<c,r,ch> in CATxREVxCHURN} >= 0 <= n[c,r,ch]
      , MaxChurnMisMatch >= 0, Proportion >= 0 <= 1
    ;

    /* From OP:
       Suppose I need to select 3000 customers from category A, 
       and 3000 customers from category B. */
    num goal = 3000;
    /* See "implicit slice" for the parenthesis notation, i.e. (c) below. */
    impvar ChooseByCat{c in CAT} = 
        sum{<(c),r,ch> in CATxREVxCHURN} Choose[c,r,ch];
    con MatchCatGoal{c in CAT}:
        ChooseByCat[c] = goal;

    /* From OP:
       From the second category, within each A and B, 
       I need to select an equal amount from 1 and 2 */
    con MatchRevenueGroupsWithinCat{c in CAT}:
        sum{<(c),(1),ch> in CATxREVxCHURN} Choose[c,1,ch]
      = sum{<(c),(2),ch> in CATxREVxCHURN} Choose[c,2,ch]
    ;

    /* From OP: 
       If possible, I need to select a proportional amount 
       across each 1, 2, and 3 subcategories. */
    con MatchBandProportion{<c,r,ch> in CATxREVxCHURN, sign in / 1 -1 /}:
        MaxChurnMismatch >= sign * ( Choose[c,r,ch] - Proportion * n[c,r,ch] );

    min MaxMismatch = MaxChurnMismatch;

    solve;

    print ChooseByCat;
    impvar IdealProportion{<c,r,ch> in CATxREVxCHURN} = Proportion * n[c,r,ch];
    print Choose IdealProportion;
    print Proportion MaxChurnMismatch;

quit;