美文网首页
sas 变量降维、变量聚类、变量去除共线性

sas 变量降维、变量聚类、变量去除共线性

作者: _瑾_瑜_ | 来源:发表于2018-05-29 11:42 被阅读0次

    今天的文章的使用场景是,是因为我很热衷处理那种别人不喜欢整理的各种流水数据,例如运营商通话流水啊,银行卡流水啊,信用卡流水等等,那么这些数据做衍生变量有个经常会碰到的问题,就是像这种“最近一天的通话次数”有可能跟“最近三天的通话次数”这种相关性很强,但是在拟合的之后,这种相关性强的只能进一个,不然共线性就来找你啦,所以这时候你要处理是:1、你要让那个变量进去。2、那些变量是一类的,他们共线性在一起很强。

    你跟我说,这谁不会啊,这不就是vif嘛,一看我就知道那几个相关性高了,是的,我们经常会有vif,但是模型做多了,你会发现,vif无论要多方便,但是有时候vif过了,但是还是存在共线性,所以你这时候还是要去看相关矩阵。所以vif并不会万能,我今天也不是要说相关矩阵,我今天要说的是sas的一个过程步叫做“proc varclus”,看着是不是很像聚类的那个过程步,是这个这个是变量的聚类,将相关性强的变量聚在一起,这里我不展开细讲,我给你链接,你自己去看,我今天不是来介绍这个过程的,我是来给代码~~

    链接在这里:http://blog.sina.com.cn/s/blog_5d3b177c0100equm.html

    https://wenku.baidu.com/view/7c4929f34693daef5ef73de1.html。

    这是思路

      代码主要实现其实就是对变量降维,而且是降维后,给你提取同类变量中那个最好的。代码的思路是这样子的:

    1、 输入一批数值变量,现在的代码只能实现数值变量的。我建议两百以内,你想要一千,我绝不拦你。

    2、 使用proc varclus过程将变量聚类,控制群的数目

            Minclusters(minc)=正整数:指定最少要有几个群。

            Maxclusters(maxc)=正整数:指定最多有几个群。

            Proportion(percent)=正有理数:群主成份所能解释的变异数百分比。注意,这里proportion=0.75与percent=75是一样的。

            Maxeigen=实数:规定每个群内第二特征值的最大可能值。

        请自行选择,本人最常使用第二特征根。

    3、 每一簇的变量都去跑一遍iv,再结合变量聚类结果指标和业务进行变量筛选。 

        挑选变量的原则如下:

            选择IV值最大的变量

            选择1-R平方最小的变量

            选择业务解释性好的变量。

    4、 选择取出这一簇里面,iv最高的或者1-R方最小的。

    5、 我知道你会说,但是我想看下其他变量的怎么样,我也给你保留了!

    代码:

    %macro varclus(DSin=,target=,Maxclusters=,group=,method=,DSout=);

    *method=1每组取iv最大;method=2每组取1-R方最小;

    %let lib=%upcase(%scan(&DSin.,1,'.'));

        %let dname=%upcase(%scan(&DSin.,2,'.'));

    proc sql noprint;

            select name into:name_list  SEPARATED by " "

            from sashelp.VCOLUMN

            where left(libname)="&lib." and left(memname)="&dname."  and lowcase(name)^=lowcase("user_id.") and lowcase(name)^=lowcase("&target") ;

        quit;

      %put &name_list.;

    ods listing close;

    ods output clusterquality=summary

              rsquare=clusters;

    proc varclus data=&DSin.

                Minclusters=2

    Maxclusters=&Maxclusters.

    percent=75

    Maxeigen=7

                outtree=fortree

                short;

    var &name_list.;

    run;

    ods listing;

    data _null_;

        set summary;

        call symput('nvar',compress(NumberOfClusters));

    run;

    data clusters_&nvar;

    set clusters;

    where NumberOfClusters=&nvar;

    run;

    data var_select;

    set clusters_&nvar;

        retain Cluster1;

        if Cluster~="" then Cluster1=Cluster;

    run;

    data _null_;

    set var_select;

    call symputx(compress("varname"||_n_),compress(Variable));

    call symputx(compress("n"),compress(_n_));

    run;

    data total_result;

    length varname$30.;

    length group_id 8.;

    length new_min 8.;

    length new_max 8.;

    length interval$30.;

    length group_num 8.;

    length bad_num 8.;

    length good_num 8.;

    length good_rate 8.;

    length bad_rate 8.;

    length woe 8.;

    length iv 8.;

    run;

    %do i=1 %to &n.;

    %put &&varname&n.;

    proc rank data=&DSin.(keep =&&varname&i. &target.) out = tmp ties = low groups = &group.;

    var &&varname&i.;

    ranks new_var;

    run;

    proc sql noprint;

    create table result1 as

    select distinct

    "&&varname&i." as varname,

    new_var,

    min(&&varname&i.) as min,

    max(&&varname&i.) as max,

    case when new_var^=. then compress(put(min(&&varname&i.),8.)||"-"||put(max(&&varname&i.),8.)) else "null " end as interval,

    count(*) as group_num,

    sum(&target.) as bad_num,

    count(*)-sum(&target.) as good_num

    from tmp

    group by new_var;

    quit;

    proc sql noprint;

    select count(*)into:good_total from tmp(where=(&target.=0));

    select count(*)into:bad_total from tmp(where=(&target.=1));

    create table result2 as

    select

    varname,

    case when new_var=. then 0 else new_var end as group_id,

    case when min=min(min) then . else min end as new_min,

    case when max=max(max) then . else max end as new_max,

    interval,group_num,bad_num,good_num,

    good_num/&good_total. as good_rate,

    bad_num/&bad_total. as bad_rate,

    log((bad_num/&bad_total.)/(good_num/&good_total.)) as woe,

    log((bad_num/&bad_total.)/(good_num/&good_total.))*((bad_num/&bad_total.)-(good_num/&good_total.)) as iv

    from result1 a;

    quit;

    proc append base=total_result data=result2 force;run;

    proc sql;

    create table iv_result as

    select distinct varname, sum(iv) as iv

    from total_result(where=(varname^=''))

    group by varname;

    quit;

    %end;

    /*合并筛选指标*/

    proc sql noprint;

    create table var_select_m as 

    select * from var_select as a left join iv_result as b on a.Variable=b.varname;

    quit;

    /*变量筛选*/

    %if &method.=1 %then %do;

    proc sort data=var_select_m;

        by Cluster1 descending iv /* iv*/;

    run;

    %end;

    %else %do;

    proc sort data=var_select_m;

        by Cluster1 RSquareRatio /* RSquareRatio*/;

    run;

    %end;

    data var_selected(where=(row=1));

    set var_select_m;

        if first.Cluster1 then row=1;

        else row+1;

        by Cluster1;

    run;

    %global var_clus;

    proc sql noprint;

    select Variable into :var_clus separated by ' '

        from Var_selected;

    quit;

    %put &var_clus;

    data &DSout.;

    set &DSin.;

    keep target &var_clus;

    run;

    %mend;

    这是代码讲解

    varclus(DSin=,target=,Maxclusters=,group=,method=,DSout=)

    DSin:你的数据集

    Maxclusters:填的是你想最多变成多少簇。

    Group:跑iv的时候你想分几组算iv。

    method:method=1每组取iv最大;method=2每组取1-R方最小;

    以上就是这个宏的参数填写,接下来我跟大家说下结果有哪些。

    结果:这个结果产出的全部数据集。主要看两张表:

    1、Var_select_d:

    保留的是每一簇筛选出来的变量,如果想换取变量,请参考下一张表。

    2、Var_select_m

    这张表保存的是每个簇的各个变量的指标。

    相关文章

      网友评论

          本文标题:sas 变量降维、变量聚类、变量去除共线性

          本文链接:https://www.haomeiwen.com/subject/hglgjftx.html