试图在给定时间点找到组内的先前最小值

时间:2017-07-20 17:07:05

标签: sas

我试图在SAS中的某个时间点找到组内的最小值。例如,我有以下数据集

ID NO| DATE      |RESULT  

1    |28NOV2015   |5.6  
1    |25JAN2016   |4.8  
1    |8MAR2016    |5.2  
1    |14MAY2016   |5.0  
1    |20JUL2016   |4.3    
1    |18SEP2016   |3.8  
2    |20AUG2012   |8.6  
2    |14NOV2012   |7.2  
2    |03JAN2013   |5.5  
2    |12MAR2013   |5.3  

我想以编程方式创建一个新列,该列将返回ID编号组中当前值之前发生的值的最小结果。结果输出应如下所示:

ID NO| DATE       |RESULT |PMINVAL  
-----|------------|-------|--------  
1    |28NOV2015   |5.6    |5.6  
1    |25JAN2016   |4.8    |5.6  
1    |8MAR2016    |5.2    |4.8  
1    |14MAY2016   |5.0    |4.8  
1    |20JUL2016   |4.3    |4.8  
1    |18SEP2016   |3.8    |4.3  
2    |20AUG2012   |8.6    |8.6  
2    |14NOV2012   |7.2    |8.6  
2    |03JAN2013   |5.5    |7.2  
2    |12MAR2013   |5.3    |5.5  

我尝试通过将滞后函数与一些条件语句结合使用来实现此目的。我不认为这种方法会起作用,因为当与条件一起使用时,滞后函数会计算满足条件的最后一条记录,这就是本例所需的。我首先创建了一个额外的列来定义"基线"或每个ID组中的第一个记录,用作前两个PMINVAL记录的参考,因为这些记录始终是基线结果值。

data MDX2;  
set MDX1;  
count + 1;  
by ID_NO;  
if first.ID_NO then count=1;  
run;  
data MDX3;  
set MDX2;  
if count <=2 then PMINVAL=BLRESULT;  
if count >2 and lag(PMINVAL)<=lag(RESULT) then PMINVAL=lag(PMINVAL);  
if count >2 and lag(PMINVAL)>lag(RESULT) then PMINVAL=lag(RESULT);  
run;

2 个答案:

答案 0 :(得分:2)

只需使用MIN()函数并保留该值即可。在计算新的最小值之前输出值。如果您每天最多只有一个结果,这将有效。

data have ;
  input id date result;
  informat date date. ;
  format date date9.;
cards;
1 28NOV2015 5.6
1 25JAN2016 4.8
1  8MAR2016 5.2
1 14MAY2016 5.0
1 20JUL2016 4.3
1 18SEP2016 3.8
2 20AUG2012 8.6
2 14NOV2012 7.2
2 03JAN2013 5.5
2 12MAR2013 5.3
;

data want;
  set have ;
  by id date;
  if first.id then pminval=result;
  retain pminval;
  output;
  pminval=min(pminval,result);
run;

如果您每天有多个结果,那么您可能需要添加另一个变量和一些额外的逻辑。

data want;
  do until (last.date);
    set have ;
    by id date;
    if first.id then pminval=result;
    daymin=min(daymin,result);
    output;
  end;
  retain pminval;
  pminval=min(pminval,daymin);
  drop daymin;
run;

答案 1 :(得分:1)

使用RETAIN和DATA步骤:

DATA have;
INPUT ID_NO DATE :DATE9. RESULT;
FORMAT DATE DATE9.;
DATALINES;
1 28NOV2015 5.6
1 25JAN2016 4.8
1 8MAR2016 5.2
1 14MAY2016 5.0
1 20JUL2016 4.3
1 18SEP2016 3.8
2 20AUG2012 8.6
2 14NOV2012 7.2
2 03JAN2013 5.5
2 12MAR2013 5.3
;


DATA want;

    SET have;
    BY ID_NO;

    RETAIN PRIOR_RESULT;
    RETAIN PRIOR_PMINVAL;

    /* "Reset" the PMINVAL when first record in set is reached */
    IF FIRST.ID_NO THEN DO;
        PMINVAL = RESULT;
        PRIOR_RESULT = RESULT;
        PRIOR_PMINVAL = RESULT;
    END;

    /* Return the MIN between the prior RESULT and PMINVAL values */
    ELSE DO;
        PMINVAL = MIN(PRIOR_RESULT,PRIOR_PMINVAL);
        PRIOR_RESULT = RESULT;
        PRIOR_PMINVAL = PMINVAL;
    END;

    DROP PRIOR_RESULT PRIOR_PMINVAL;

RUN;

<强>结果:
enter image description here