我试图在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;
答案 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;