SAS删除组内满足条件的观察

SAS to delete observations that meet condition within group

我想删除 Have 数据集中满足以下所有条件的记录。 ID_num这里代表ID字段的3位数字部分

下面是 Have 和所需的输出。

data have;
     input ID $ Type $ Drug $;
     cards;
M001    blood A
M001    blood A
M001    blood A
M001    blood B
M001    blood B
M001    milk  B
M001    blood C
M001    blood C
M002    blood A
M002    blood A
Inf002  blood A
M002    blood A
M002    blood B
M002    milk  C
Inf003  blood B
M003    blood B
;
run;
data want;
     input ID $ Type $ Drug $;
     cards;
M001    milk   B
Inf002  blood  A
M002    blood  A
M002    milk   C
Inf003  blood  B
M003    blood  B
;
run;

例如inf002药物A观察下的M002(血液,药物A),因为它出现在同一药物组的婴儿样本之后。但上面的两个 M002(血液,A)观察结果应该被删除,因为它们发生在同一药物组的第一个婴儿样本之前。相反,M001(牛奶,B)之后的两个M001(血液,C)观察应删除,因为药物组不同。

编辑:分组依据(gpDrug)。

  1. 使用SAS regex(此处为prxmatch(patt, var))提取ID分组数(代码中为gp)。

  2. 可以检查保留条件 row-by-row 同时也可以按 (gp, Drug) 分组。 gp 中的更改由 FIRST.drug 标识。

    • 在使用BY 语句之前,必须对数据集进行排序。由于 SAS 排序稳定,原始排序不会中断。
    • 可以通过在正则表达式解析阶段记录 _n_ 来跟踪原始顺序。

代码

* "have" is in your post;
data tmp;
    set have;
    pos = prxmatch('(\d{3})', ID);
    gp = substr(ID, pos, pos+2);  * group number;
    mi = substr(ID, 1, 1);  * mother or infant;
    n = _n_; * keep track of the original ordering;
    drop pos;
run;

proc sort data=tmp out=tmp;
    by gp drug;
run;

data want(drop=flag_keep gp mi);
    set tmp;
    by gp drug;
    * state variables;
    retain flag_keep 0;
    if FIRST.drug then flag_keep = 0;
    * mark keep;
    if (flag_keep = 1) or (mi = "I") or ((mi = "M") and (Type = "milk"))
        then flag_keep = 1;
    if flag_keep = 1 then output;
run;

proc sort data=want out=want;
    by n;
run;

结果:为清楚起见,显示了原始行号 n

   ID      Type   Drug  n
1  M001    milk   B     6    
2  Inf002  blood  A     11    
3  M002    blood  A     12    
4  M002    milk   C     14    
5  Inf003  blood  B     15    
6  M003    blood  B     16