SAS"目标寻求"与数据转换

时间:2017-03-22 17:57:49

标签: sas

我试图在SAS中复制Excel的目标搜索。 我想找到一个常数,当添加到初始数据时,数据的总体平均值等于目标。当涉及转换时,这会有点棘手。

所以我的三个数据点(var1)是0.78,0.8,0.85。目标是0.87。 我想找到x其中AVERAGE(1 /(1 + EXP( - (LN(var1 /(1 + var1))+ x)))= 0.87

这是我目前的代码,但是当它应该是0.4525(通过Excel找到)时,它得到x = 0.4803。

data aa;
     input var1 target;
     datalines;
0.78 0.87
0.8 0.87
0.85 0.87
;
run;

proc model data=aa outparms=parm;
target = 1/(1+EXP(-(log(var1/(1-var1)) + x)));
fit target;
run;

我认为这不起作用bc它并不包含所有3个数据点的平均值。我不知道该怎么做。理想情况下,我只能将proc模型节点中的第二行更改为:

target = Avg(1/(1+EXP(-(log(var1/(1-var1)) + x))));

但这不起作用。

1 个答案:

答案 0 :(得分:0)

proc model主要用于时间序列,并且在垂直使用汇总函数方面做得不好;但是,水平做它时效果很好。解决问题的一种方法是转移问题:

proc transpose data=aa out=aa_trans;
    by target;
    var var1;
run;

proc model data=aa_trans;
    endo x;
    exo COL1-COL3 target;

    target = mean(1/(1+EXP(-(log(COL1/(1-COL1)) + x)))
                , 1/(1+EXP(-(log(COL2/(1-COL2)) + x)))
                , 1/(1+EXP(-(log(COL3/(1-COL3)) + x))) );

    solve / out=solution solveprint ;
run;

我们得到 0.4531398172 的答案。可以通过直接插入值来检查:

data _null_;
    set aa_trans;

    x = 0.4531398172;

    check = mean(1/(1+EXP(-(log(COL1/(1-COL1)) + x)))
               , 1/(1+EXP(-(log(COL2/(1-COL2)) + x)))
               , 1/(1+EXP(-(log(COL3/(1-COL3)) + x))) );

    put '*********** ' check;
run;

此方法需要额外的宏编程来进行概括,如果您有许多观察转置,则可能在计算上非常昂贵。要对任何给定数量的列进行概括,可以使用以下宏程序:

%macro generateEquation;
    %global eq;

    %let eq = ;

    proc sql noprint;
        select count(*)
        into :total
        from aa
        ;
    quit;

    %do i = 1 %to &total.;
        %let eq = %cmpres(&eq 1/(1+EXP(-(log(COL&i/(1-COL&i))+x))));
    %end;

    %let eq = mean(%sysfunc(tranwrd(&eq, %str( ), %str(,) ) ) );

    %put &eq;
%mend;
%generateEquation;

proc model data=aa_trans;
    endo x;
    exo COL1-COL3 target;

    target = &eq.;

    solve / out=solution solveprint ;
run;

相反,您可能希望将此问题重新设置为没有目标函数的优化问题。 proc optmodel,如果在您的网站上可用,则允许您执行此矩阵操作。生成的代码更加复杂和手动,但会为您提供更通用和计算上可行的结果。

您需要添加两个新变量并将目标分离到新数据集。

data aa;
     input targetid obs var1;
     datalines;
1 1 0.78
1 2 0.8
1 3 0.85
;
run;

data bb;
    input targetid target;
    datalines;
1 0.87
;
run;

proc optmodel;
    set id;
    set obs;
    set <num,num> id_obs;

    /* Constants */
    number target{id};
    number var1{id_obs};

    read data bb into id=[targetid]
        target;

    read data aa into id_obs=[targetid obs]
        var1;

    /* Parameter of interest */
    var x{id};

    /* Force the solver to seek the required goal */
    con avg {i in id}: target[i] = sum{<j,n> in id_obs: j=i} (1/(1+EXP(-(log(var1[j, n]/(1-var1[j, n])) + x[i]))) ) 
                                 / sum{<j,n> in id_obs: j=i} 1;

    /* Check if it's the equation that we want */
    expand;

    /* Solve using the non-linear programming solver with no objective */
    solve with nlp noobjective;

    /* Output */
    create data solution from [targetid] = {i in id}
        x[i];
quit; 

optmodel会返回一个类似的答案: 0.4531395426 ,相差0.0000002746个小数位。由于方法和最优公差的不同,答案并不相同;但是,解决方案会检出。

proc sql;
    select Avg(1/(1+EXP(-(log(var1/(1-var1)) + 0.4531395426))))
    from aa;
quit;