zoukankan      html  css  js  c++  java
  • sas单变量的特征分析

    sas单变量的特征分析

    大炮,我有个烦恼,我领导最近老叫我单变量结合因变量分析,但是都是分段分析,我总是写proc sql然后group by ,但是这个过程好无聊啊,有木有什么新的代码,让我可以分析的快点啊。

    最近写了个宏,刚好可以解决你这个问题,在上代码之前,先来个结果图

    詹大炮

    这个结果对于分析来说是不好的,因为这个结果没啥实际意义,说白了就是跟因变量没关系,但是这个图我们不是要来讲变量怎么有用,我们要介绍的是这段代码最后呈现的一个结果是怎样的。

    代码:

    %macro ChcAnalysis(DSin, DVVar, VarX, NBins, Method, DSChc);

    proc sort data=&DSin;

    by &VarX;

    run;

    Data temp;

    set &DSin ;

    by &VarX;

    _Obs=_N_;

    keep &DVVAr &VarX _Obs;

    run;

    proc sql noprint;

    %if &Method=1 %then %do;

    select count(&DVVar) into :N from temp;

    select max(_Obs), min(_Obs) into :Vmax, :Vmin from temp;

    %let BinSize=%sysevalf((&Vmax)/&Nbins);

    %let LB_1=0;

    %do i=1 %to %eval_r(&Nbins-1);

    %let LB_&i=%sysevalf(&LB_1 (&i-1)*&BinSize);

    %let UB_&i=%sysevalf(&&LB_&i &BinSize);

    select sum(&DVVar) , count(*) into :Sum_&i , :N_&i from temp

    where _obs>=&&Lb_&i and _obs<&&Ub_&i;

    %end;

    %let LB_&NBins=%sysevalf(&LB_1 (&NBins-1)*&BinSize);

    %let UB_&NBins=&Vmax;

    select sum(&DVVar) , count(*) into :Sum_&i , :N_&i from temp

    where _obs>=LB_&NBins and _obs<=UB_&NBins;

    %end;

    %else %do ;

    select count(&DVVar) into :N from temp;

    select max(&VarX), min(&VarX) into :Vmax, :Vmin from temp;

    %let BinSize=%sysevalf((&Vmax-&Vmin)/&Nbins);

    %let LB_1=&Vmin;

    %do i=1 %to %eval_r(&Nbins-1);

    %let LB_&i=%sysevalf(&LB_1 (&i-1)*&BinSize);

    %let UB_&i=%sysevalf(&&LB_&i &BinSize);

    select sum(&DVVar) , count(*) into :Sum_&i , :N_&i from temp

    where &VarX>=&&Lb_&i and &VarX<&&Ub_&i;

    %end;

    %let LB_&NBins=%sysevalf(&LB_1 (&NBins-1)*&BinSize);

    %let UB_&NBins=&Vmax;

    select sum(&DVVar) , count(*) into :Sum_&i , :N_&i from temp

    where &VarX>=&&Lb_&i and &VarX<=&&UB_&i;

    %end;

    quit;

    data &DSChc;

    %do i=1 %to &NBins;

    Bin=&i;

    LowerBound=&&LB_&i;

    UpperBound=&&UB_&i;

    if (&&sum_&i =. ) then N_1=0; else N_1=&&Sum_&i;

    if &&N_&i=. then BinTotal=0; else BinTotal=&&N_&i;

    N_0 = BinTotal-N_1;

    Percent_1=100*N_1/BinTotal;

    Percent_0=100*N_0/BinTotal;

    output;

    %end;

    Run;

    proc datasets nodetails nolist library=work;

    delete temp;

    run;

    quit;

    %mend;

    詹大炮

    还是老样子,分段介绍。

    01

    % ChcAnalysis(DSin, DVVar, VarX, NBins, Method, DSChc);

    DSin:填入的是原数据集;

    DVVar:填入因变量,这里我们分析的是二元的因变量,所以因变量一定要是二元的,并且必须是数值的0,1。因为在代码中设定的就是这样子的,至于你问我为什么不能是字符,那是因为我还没能耐写字符的。

    VarX:你要分析的变量(数值的哈)

    NBins:分几段分析。结果的例子是分了5段;

    Method:怎么分。1-等高度分,2-等宽度分。我的结果图那个是按2分的。

    DSChc:结果数据集的输出名字。

    02

    proc sort data=&DSin;by &VarX;run;

    Data temp;

    set &DSin ;

    by &VarX;

    _Obs=_N_;

    keep &DVVAr &VarX _Obs;

    run;

    将原数据集中的变量排序,后面的分组的时候要用到。然后保留要分析的变量在temp数据集中,产生变量_Obs,作为序号,这是等高度分析的时候要用的。等高度的意思就是每个区间的数量是一样的,等宽度的意思是,区间的的差值是一样的。两个不同的情况,在分析的时候,如果等宽的结果你觉得不是很明显可以分析的话,就换等高,任意切换哈。

    temp的数据集是长这样子的:

    _obs是观测的序号。

    03

    proc sql noprint;

    %if &Method=1 %then %do;

    select count(&DVVar) into :N from temp;

    select max(_Obs), min(_Obs) into :Vmax, :Vmin from temp;

    %let BinSize=%sysevalf((&Vmax)/&Nbins);

    %let LB_1=0;

    %do i=1 %to %eval_r(&Nbins-1);

    %let LB_&i=%sysevalf(&LB_1 (&i-1)*&BinSize);

    %let UB_&i=%sysevalf(&&LB_&i &BinSize);

    select sum(&DVVar) , count(*) into :Sum_&i , :N_&i from temp

    where _obs>=&&Lb_&i and _obs<&&Ub_&i;

    %end;

    %let LB_&NBins=%sysevalf(&LB_1 (&NBins-1)*&BinSize);

    %let UB_&NBins=&Vmax;

    select sum(&DVVar) , count(*) into :Sum_&i , :N_&i from temp

    where _obs>=LB_&i. and _obs<=UB_&i.;

    %end;

    %else %do ;

    select count(&DVVar) into :N from temp;

    select max(&VarX), min(&VarX) into :Vmax, :Vmin from temp;

    %let BinSize=%sysevalf((&Vmax-&Vmin)/&Nbins);

    %let LB_1=&Vmin;

    %do i=1 %to %eval_r(&Nbins-1);

    %let LB_&i=%sysevalf(&LB_1 (&i-1)*&BinSize);

    %let UB_&i=%sysevalf(&&LB_&i &BinSize);

    select sum(&DVVar) , count(*) into :Sum_&i , :N_&i from temp

    where &VarX>=&&Lb_&i and &VarX<&&Ub_&i;

    %end;

    %let LB_&NBins=%sysevalf(&LB_1 (&NBins-1)*&BinSize);

    %let UB_&NBins=&Vmax;

    select sum(&DVVar) , count(*) into :Sum_&i , :N_&i from temp

    where &VarX>=&&Lb_&i and &VarX<=&&UB_&i;

    %end;

    quit;

    我知道你肯定要说,这密密麻麻的% &*我不想看。但是你看下嘛,不难的,我介绍介绍给你看嘛。

    首先这段代码需要分成两步来看,第一步是当我们的&Method=1 的情况执行do后面的程序,反之,则是当我们的&Method=2的时候的情况啦。

    然后我们来讲&Method=1情况时执行的代码:

    select count(&DVVar) into :N from temp;

    select max(_Obs), min(_Obs) into :Vmax, :Vmin from temp;

    第一个select赋值宏是算出全部的观测数。

    第二个select是算出最大的那个序号,其实我个人觉得这步有点多 余,你想直接用n也可以的,只是我想跟&Method=2的思路一样,所以就没删。

    %let BinSize=%sysevalf((&Vmax)/&Nbins);

    %let LB_1=0;

    %do i=1 %to %eval_r(&Nbins-1);

    %let LB_&i=%sysevalf(&LB_1 (&i-1)*&BinSize);

    %let UB_&i=%sysevalf(&&LB_&i &BinSize);

    select sum(&DVVar) , count(*) into :Sum_&i , :N_&i from temp

    where _obs>=&&Lb_&i and _obs<&&Ub_&i;

    %end;

    BinSize因为是&Method=1,所以这里BinSize是区间的差值,这里有个宏函数%sysevalf就自己百度下用法吧,这里就不介绍了。%do i=1 %to %eval_r(&Nbins-1);这一步就开始循环,这里为什么只循环到倒数第二个呢,是因为倒数第一个直接就是剩下的全部,就不需要再区间限制了。

    %let LB_&i=%sysevalf(&LB_1 (&i-1)*&BinSize);

    %let UB_&i=%sysevalf(&&LB_&i &BinSize);

    这两步是产生这个分组的上下区间,然后用于后面的select语句中的where条件,把该区间的数量统计出来。

    select sum(&DVVar) , count(*) into :Sum_&i , :N_&i from temp

    where _obs>=&&Lb_&i and _obs<&&Ub_&i;

    %end;

    这个过程特别注意的就是sum(&DVVar),是用sum,这就是我一开始为什么说因变量是二元的,而且要是0,1的情况就是方便这里统计啦。

    %let LB_&NBins=%sysevalf(&LB_1 (&NBins-1)*&BinSize);

    %let UB_&NBins=&Vmax;

    select sum(&DVVar) , count(*) into :Sum_&i , :N_&i from temp

    where _obs>=LB_&i. and _obs<=UB_&i.;

    %end;

    这就是第四步啦,

    %let LB_&NBins=%sysevalf(&LB_1 (&NBins-1)*&BinSize);

    %let UB_&NBins=&Vmax;

    产生最后的区间,这里的i是5了,其实我一直很不能理解到这步,为什么还可以输出i=5呢,不是i只循环到4吗?但是执行的时候就是这样子的,这个套路是仿照之前的等高度分变量区间的那个代码写的。

    我还特地看了日志也循环了:

    我觉得应该是sas的处理流程,在pdv层面应该可以解释,跪求大神在留言区解释。万分感激。

    那么&Method=2的部分就留给你自己去看啦,还是&Method=1的那种套路,只是等区间变量等量而已。

    04

    data &DSChc;

    %do i=1 %to &NBins;

    Bin=&i;

    LowerBound=&&LB_&i;

    UpperBound=&&UB_&i;

    if (&&sum_&i =. ) then N_1=0; else N_1=&&Sum_&i;

    if &&N_&i=. then BinTotal=0; else BinTotal=&&N_&i;

    N_0 = BinTotal-N_1;

    Percent_1=100*N_1/BinTotal;

    Percent_0=100*N_0/BinTotal;

    output;

    %end;

    Run;

    然后这部分就是以上产生的宏,拼接成结果数据集。这里应该注意的是,每循环一个,就是产生一条观测之后output到数据集,如此循环之后需知道i=&nbins为止。数据分析师培训

  • 相关阅读:
    网络测量中基于Sketch方法的简单介绍
    Reading SBAR SDN flow-Based monitoring and Application Recognition
    Reading Meticulous Measurement of Control Packets in SDN
    Reading SketchVisor Robust Network Measurement for Sofeware Packet Processing
    ovs加dpdk在日志中查看更多运行细节的方法
    后缀数组
    (转载)LCA问题的Tarjan算法
    Codeforces Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) A. Checking the Calendar(水题)
    Vijos 1816统计数字(计数排序)
    卡特兰数
  • 原文地址:https://www.cnblogs.com/amengduo/p/9587136.html
Copyright © 2011-2022 走看看