SAS 如何按 ID 汇总条件并生成多个标记变量?
结论
先按 ID 汇总每条记录是否符合对应条件,再将汇总结果合并回原数据。如果每个 ID 只需显示一行标记,可以只给输出中的 first.ID 赋值。
示例中的期望结果与“每个 ID 只标记一次”并不完全一致:ID 001 的 Flag1 有两条记录标为 Y;Flag2 标在 G5="Y" 的记录上,而不是该 ID 的首条记录上。另外,按文字描述,Relation 为 PossiblyRelated 的记录也应满足 Flag1 条件,但期望结果将该行标为 N。下面的代码按文字描述中的规则处理,请根据实际业务规则调整。
按 ID 汇总,只在首条记录显示
PROC SQL 中的 GROUP BY ID 可以计算每个 ID 的汇总值。用 MAX 汇总 0/1 条件标记时,只要组内有一条记录符合条件,结果就是 1。
proc sql;
create table id_flags as
select ID,
max(Relation in ("Related", "PossiblyRelated")) as Flag1_num,
max(G5 = "Y") as Flag2_num
from mydataset
group by ID;
quit;
proc sort data=mydataset;
by ID;
run;
proc sort data=id_flags;
by ID;
run;
data desired;
merge mydataset(in=in_data) id_flags;
by ID;
if in_data;
length Flag1 Flag2 $1;
if first.ID then do;
Flag1 = ifc(Flag1_num, "Y", "N");
Flag2 = ifc(Flag2_num, "Y", "N");
end;
else do;
Flag1 = "N";
Flag2 = "N";
end;
drop Flag1_num Flag2_num;
run;
这里的 Flag1 和 Flag2 表示整个 ID 组是否曾满足对应规则,并且只显示在按 ID 排序后的首条记录上。其他记录设为 N。如果希望其他行留空,可以把 else 分支改为:
else call missing(Flag1, Flag2);
first.ID 是 SAS BY-group 处理中自动生成的临时变量。使用前,数据必须按 ID 排序。同一 ID 有多条记录时,哪条记录算首条取决于排序后的顺序。
如果要标记首条符合条件的记录
如果需求是每个 ID 只在“第一条符合条件的记录”上标记 Y,而不是把 ID 的汇总结果放在首条记录上,可以用 BY-group 处理和保留状态:
data desired_first_match;
set mydataset;
by ID;
length Flag1 Flag2 $1;
retain found1 found2;
if first.ID then do;
found1 = 0;
found2 = 0;
end;
Flag1 = "N";
Flag2 = "N";
if not found1 and Relation in ("Related", "PossiblyRelated") then do;
Flag1 = "Y";
found1 = 1;
end;
if not found2 and G5 = "Y" then do;
Flag2 = "Y";
found2 = 1;
end;
drop found1 found2;
run;
这段代码会分别标记每个 ID 中首次符合 Flag1 和 Flag2 条件的记录。数据需要先按 ID 排序。如果要按日期或其他字段确定“首次”,应先按 ID 和该字段排序。
扩展到更多规则
每条规则都可以先转换为 0/1,再按 ID 使用 MAX 汇总。例如,新增一个条件为 Type="A" 的 Flag3:
max(Type = "A") as Flag3_num
数据量较大或规则较多时,集中计算汇总标记再合并回原表,通常更容易维护。需要区分的是“每个 ID 是否满足条件”和“哪条记录满足条件”:前者是组级汇总,后者需要确定要标记哪条记录。
备注:内容仅供参考。
