当其观察不包含 SAS 中的某些值时删除组

Delete group when its observation does not contain certain values in SAS

参考下文table,如果一个ID中至少有一个组有第1天到第3天(允许重复),则该ID被认为是完整的。 我需要删除组没有完整的第 1 天到第 3 天的 ID。

ID   Group     Day
1     A        1
1     A        1
1     A        2
1     A        3
1     B        1
1     B        3
2     A        1
2     A        3
2     B        2

预期结果

ID   Group     Day
1     A        1
1     A        1
1     A        2
1     A        3
1     B        1
1     B        3

有了这个参考, 我试过下面的代码,但它无法删除 ID 2。

PROC SQL;
CREATE TABLE TEMP AS SELECT
* FROM HAVE
GROUP BY ID
HAVING MIN(DAY)=1 AND MAX(DAY)=3
;QUIT;

PROC SQL;
CREATE TABLE TEMP1 AS SELECT
* FROM TEMP WHERE ID IN
(SELECT ID FROM TEMP
WHERE DAY=2)
;QUIT;

您可以查询带移除列表的数据集。例如:

proc sql noprint;
    create table want as
        select *
        from have
        where cats(group, id) NOT IN(select cats(group, id) from removal_list)
    ;
quit;

创建删除列表

此方法将使您不必对所有 ID、组和日期进行笛卡尔积来创建删除列表。

假设您的数据按 IDgroupday 排序。

  1. 对于每个ID,组中的第一天必须是1
  2. 对于每个ID,第一天之后组中的所有天都必须与前一天相差1

代码:

data removal_list;
    set have;
    by ID Group Day;
    retain flag_remove_group;

    lag_day = lag(day);

    /* Reset flag_remove_group at the start of each (ID, Group).
       Check if the first day is > 1. If it is, set the removal flag.
    */
    if(first.group) then do;
        call missing(lag_day);

        if(day > 1) then flag_remove_group = 1;
            else flag_remove_group = 0;
    end;

    /* If it's not the first (ID, Group), check if days 
       are skipped between observations 
    */
    if(NOT first.group AND (day - lag_day) NE 1) then flag_remove_group = 1;

    if(flag_remove_group) then output;

    keep id group;
run;

所以您想找到一组 ID 值,其中 ID 至少有一个 GROUP 具有所有三个 DAY 值?查找 ID 列表作为子查询,并使用它对原始数据进行子集化。

子查询中的关键是您希望 DAY 有 3 个不同的值。如果您的数据可能有其他的 DAY 值(例如 missing 或 4),则使用 WHERE 子句仅保留您要计算的值。

proc sql;
create table want as
  select * from have
  where id in 
   (select id from have 
    where day in (1,2,3)
    group by id,group
    having count(distinct day)=3
   )
;
quit;