当其观察不包含 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、组和日期进行笛卡尔积来创建删除列表。
假设您的数据按 ID
、group
和 day
排序。
- 对于每个ID,组中的第一天必须是1
- 对于每个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;
参考下文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
有了这个参考,
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、组和日期进行笛卡尔积来创建删除列表。
假设您的数据按 ID
、group
和 day
排序。
- 对于每个ID,组中的第一天必须是1
- 对于每个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;