我试图在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可能无法选择这些数字较低的最大客户数,我回去手动选择客户。
答案 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;