如何用SAS宏生成姓名列表的无重复nCr组合数据集?
SAS宏%create_name_combination补全方案
需求说明
基于包含唯一姓名的输入数据集name_list,生成指定数量(如3个)姓名的无重复无序全组合数据集——同一组合内无重复姓名,且不同顺序的同一组合仅保留一条记录(如A,B,C与C,B,A视为同一组合,只输出一次)。
补全后的完整宏代码
%macro create_name_combination(in_ds=, out_ds=, k=); /* 1. 获取姓名列表及总数量,用于后续序号判断 */ proc sql noprint; select name into :name_list separated by ' ' from &in_ds.; select count(*) into :name_count from &in_ds.; quit; /* 2. 生成k层循环的笛卡尔积,通过序号过滤去重 */ data &out_ds.; set &in_ds.(rename=(name=name1) keep=name); %do i=2 %to &k.; set &in_ds.(rename=(name=name&i.) keep=name) point=&i._ptr nobs=&i._nobs; /* 核心过滤:确保后一个姓名在列表中的序号大于前一个,避免重复组合 */ if whichc(name&i., &name_list.) > whichc(name%eval(&i.-1), &name_list.); %end; /* 保留所有姓名变量 */ keep name1-name&k.; run; /* 可选:将宽表转为长表格式(按需启用) */ /* proc transpose data=&out_ds. out=&out_ds._long(rename=(col1=name) drop=_name_); var name1-name&k.; run; */ %mend create_name_combination; /* 调用示例:生成3个姓名的无重复组合 */ %create_name_combination(in_ds=name_list, out_ds=want, k=3);
关键逻辑解释
- 姓名列表预处理:通过
proc sql提取所有姓名到宏变量name_list,并统计总人数,为后续的序号判断提供依据。 - 多层循环与去重过滤:
- 使用
set point=实现多层循环的笛卡尔积生成; - 通过
whichc函数获取每个姓名在列表中的位置序号,强制要求后一个姓名的序号大于前一个,从根源上避免重复组合(如只会生成A,B,C,不会生成B,A,C或A,C,B等重复项)。
- 使用
- 输出格式可选:默认输出宽表(每个观测一行,包含
name1-namek变量),若需要长表格式,可启用注释的proc transpose代码。
内容的提问来源于stack exchange,提问作者user860374
相关产品推荐
相关产品推荐

