SAS:如何找出每个变量列的后续第二高条目?

时间:2016-02-02 06:47:37

标签: csv sas

我有一个CSV格式的数据集如下:

Policy_Number,var1,var2,var3,Exposure
1,B,H,J,191
2,B,F,Unknown,174
3,C,Unknown,I,153
4,B,G,L,192
5,Unknown,E,Unknown,184
6,D,E,K,113
7,C,Unknown,I,140
8,A,H,I,133
9,C,F,I,194
10,Unknown,G,Unknown,105
11,B,H,L,172
12,A,Unknown,I,198
13,D,E,K,155
14,Unknown,G,K,177
15,B,H,Unknown,100
16,D,Unknown,J,176
17,B,E,I,112
18,Unknown,E,J,192
19,C,Unknown,K,146
20,C,G,Unknown,187

我想找出最高和第二高的'曝光'每个变量的值为Var1,Var2,Var3。

随后输出文件必须如下:

VariableName  VariableValue  Max_Exposure  Exposure_Percentage
   Var1            A             198
   Var1            A             133
   Var1            B             192
   Var1            B             191
   Var1            C             194
   Var1            C             187
   Var1            D             176
   Var1            D             155
   Var1          Unknown         192           
   Var1          Unknown         184
   Var2            E             192
   Var2            E             184
   Var2            F             194
   Var2            F             174
   Var2            G             192
   Var2            G             187
   Var2            H             191
   Var2            H             172
   Var2          Unknown         198
   Var2          Unknown         176
   Var3            I             198
   Var3            I             194
   Var3            J             192
   Var3            J             191
   Var3            K             177
   Var3            K             155
   Var3            L             192
   Var3            L             187
   Var3          Unknown         184
   Var3          Unknown         194

其中Exposure_Percentage是每个VariableValue的曝光百分比。

我正在以非常原始的方式做到这一点。我正在创建3个表并找出每个表的最大和第二个最大曝光,然后我合并这3个表。但是如果增加VariableName,则会在数据中引入更多列,那么我的方法将失败。相同的代码如下:

data try2;
infile 'complex.csv' dsd dlm = ',' FIRSTOBS = 2;
Length Policy_Number Var1 $ 10 Var2 $ 10 Var3 $ 10 Exposure 3;
input Policy_Number $ Var1 $ Var2 $ Var3 $ Exposure;
run;

proc sort data = try2;
by Var3 descending Exposure;
run;
data need2;
set try2;
by Var1;
if first.var1 then n=0;
n+1;
if n=1 then output;
if n=2 then output;
run;

请告诉我这些问题的可能解决方案。 提前谢谢。

2 个答案:

答案 0 :(得分:1)

首先定义有多少变量:

%let num_vars=3;

启动datastep并定义数组以保存第一个观察中的变量名称以及每行的值。

data IN(keep=VARIABLENAME VARIABLEVALUE EXPOSURE);
  array VAR(&num_vars) $10.;
  array VAL(&num_vars) $10.;

    retain VAR1-VAR&num_vars.;
    length VARIABLENAME VARIABLEVALUE $8 EXPOSURE 8.;

  infile cards dsd ;
    if _n_ = 1 then do;
        input;
        do i = 1 to &num_vars.;
            VAR(i) = scan(_infile_,i+1,",");
        end;
    end;

这是输入步骤,它读入变量然后将它们存储在数组中,然后输出它们:

  input POLICY_NUMBER @ ;
  do i = 1 to &num_vars;
    VARIABLENAME=VAR(i);
    input VAL(i) $ @;
  end;
  input EXPOSURE;

  do i = 1 to &num_vars;
    VARIABLENAME=VAR(i);
    VARIABLEVALUE=VAL(i);
    output;
  end;

cards;
Policy_Number,var1,var2,var3,Exposure
1,B,H,J,191
2,B,F,Unknown,174
3,C,Unknown,I,153
4,B,G,L,192
5,Unknown,E,Unknown,184
6,D,E,K,113
7,C,Unknown,I,140
8,A,H,I,133
9,C,F,I,194
10,Unknown,G,Unknown,105
11,B,H,L,172
12,A,Unknown,I,198
13,D,E,K,155
14,Unknown,G,K,177
15,B,H,Unknown,100
16,D,Unknown,J,176
17,B,E,I,112
18,Unknown,E,J,192
19,C,Unknown,K,146
20,C,G,Unknown,187
;
run;

按照您想要的顺序对变量进行排序:

proc sort data=IN; by VARIABLENAME VARIABLEVALUE descending EXPOSURE ; run;

使用CNT变量保留最大值的前2个实例。

data GET_MAX(drop=CNT);
set IN;
by VARIABLENAME VARIABLEVALUE descending EXPOSURE;
  if first.VARIABLEVALUE then call missing(of CNT);

  CNT+1;
  if CNT in (1,2);
run;

然后计算您的百分比:

proc sql;
create table OUT as
  select VARIABLENAME
            , VARIABLEVALUE
            , EXPOSURE
            , (EXPOSURE/sum(EXPOSURE))*100 as EXPOSURE_PERCENTAGE format=8.2
    from
        GET_MAX
    group by 1,2
;quit;

使用proc摘要获得总和:

proc summary data=GET_MAX nway;
var EXPOSURE    ;
class VARIABLENAME VARIABLEVALUE;
output out=work.TEST(drop=_TYPE_ _FREQ_ )
sum=EXPOSURE_SM ;
run; 

答案 1 :(得分:1)

我已使用proc summary计算最高2次曝光,并使用idgroup函数。这将值放在2列而不是2行中,因此需要后续数据步骤将数据转换为所需格式。然而,初始布局确实可以更容易地计算数据步骤中的百分比。

/* input csv data */
data try2;
infile datalines dsd;
Length Policy_Number Var1 $ 10 Var2 $ 10 Var3 $ 10 Exposure 3;
input Policy_Number $ Var1 $ Var2 $ Var3 $ Exposure;
datalines;
1,B,H,J,191
2,B,F,Unknown,174
3,C,Unknown,I,153
4,B,G,L,192
5,Unknown,E,Unknown,184
6,D,E,K,113
7,C,Unknown,I,140
8,A,H,I,133
9,C,F,I,194
10,Unknown,G,Unknown,105
11,B,H,L,172
12,A,Unknown,I,198
13,D,E,K,155
14,Unknown,G,K,177
15,B,H,Unknown,100
16,D,Unknown,J,176
17,B,E,I,112
18,Unknown,E,J,192
19,C,Unknown,K,146
20,C,G,Unknown,187
;
run;

/* calculate highest 2 exposures for each variable */
proc summary data=try2;
class var: ;
ways 1;
output out=want (drop=_:) idgroup(max(exposure) out[2] (exposure)=) / autoname;
run;

/* merge Var fields into 1 and output 1 row per exposure */
data want1;
set want;
_expsum = sum(of exposure:); /* sum exposures to calculate percentages later on */
array vars var:; /* create array of Var variables */
array exp exposure:; /* create array of Exposure variables */
do i=1 to dim(vars); /* loop through Var variables and keep non-missing values */
    if not missing(vars{i}) then do;
        variablename=vname(vars{i});
        variablevalue=vars{i};
    end;
end;
do j=1 to dim(exp); /* loop through Exposures, output each one and calculate percentage of total */
    max_exposure = exp{j};
    exposure_percentage = exp{j}/_expsum;
    output;
end;
format exposure_percentage percent10.1;
drop var1--var3 exposure_1 exposure_2 _expsum i j; /* drop unwanted variables */
run;

/* sort data in required order */
proc sort data=want1;
by variablename variablevalue descending max_exposure;
run;