SAS横向合并列遇BY值重复致多对多,求可行解决方案
解决SAS中多对多合并问题,实现自定义横向列合并
你遇到的问题很典型:当多个数据集的BY变量存在重复值时,SAS的MERGE语句会执行多对多合并——也就是每个数据集的所有匹配观测两两组合,这自然会得到不符合预期的结果。要实现你想要的自定义列填充,我们需要先给每个观测分配对应的目标行号,再基于ID+行号进行合并,或者直接用数组构建目标数据集。
方法一:拆分数据集并按ID+行号合并
这个方法适合你已经拆分了数据集的场景,核心是给每个拆分后的数据集添加行号,确保合并时是一对一匹配。
步骤1:给原数据集添加组内序号
先给每个ID下的观测分配连续的序号,方便后续定位每个值的位置:
/* 原数据集 */ data have; input ID A1 $; datalines; 1 x1 1 x2 1 x3 1 x4 1 x5 1 x6 ; run; /* 添加每个ID内的序号seq */ data have_num; set have; by ID; if first.ID then seq = 0; seq + 1; run;
步骤2:拆分并添加目标行号
根据你期望的输出,把每个值分配到对应的列和行:
/* 生成A1列的数据集,包含目标行号 */ data a1_data; set have_num; where seq in (1, 2, 4); /* 对应期望中A1列的x1、x2、x4 */ row = case seq when 1 then 1 when 2 then 2 when 4 then 3 end; keep ID row A1; run; /* 生成A2列的数据集 */ data a2_data; set have_num; where seq in (3, 6); /* 对应期望中A2列的x3、x6 */ row = case seq when 3 then 1 when 6 then 2 end; keep ID row A2; run; /* 生成A3列的数据集 */ data a3_data; set have_num; where seq = 5; /* 对应期望中A3列的x5 */ row = 1; keep ID row A3; run;
步骤3:按ID+行号合并
现在每个数据集的ID+row是唯一的,合并时就会得到一对一的匹配:
data want; merge a1_data a2_data a3_data; by ID row; run;
方法二:用数组直接构建目标数据集
如果不想拆分数据集,可以用临时数组直接填充目标行和列,更高效灵活:
data want; /* 定义3行3列的临时数组,存储所有要填充的值 */ array cells[3, 3] $ _temporary_; /* 读取当前ID的所有观测,填充数组 */ do until(last.ID); set have_num; by ID; /* 根据seq把值放到数组对应的位置 */ select(seq); when(1) cells[1, 1] = A1; /* 第1行第1列(A1) */ when(2) cells[2, 1] = A1; /* 第2行第1列(A1) */ when(3) cells[1, 2] = A1; /* 第1行第2列(A2) */ when(4) cells[3, 1] = A1; /* 第3行第1列(A1) */ when(5) cells[1, 3] = A1; /* 第1行第3列(A3) */ when(6) cells[2, 2] = A1; /* 第2行第2列(A2) */ end; end; /* 输出每一行的数据 */ do i = 1 to 3; ID = 1; /* 实际使用原ID,这里因为只有一个ID所以硬编码 */ A1 = cells[i, 1]; A2 = cells[i, 2]; A3 = cells[i, 3]; output; end; /* 重置数组,避免影响下一个ID */ call missing(of cells[*]); run;
这两种方法都能得到你期望的输出,方法二更适合处理多个ID的场景,只需要调整数组大小和select语句的匹配规则即可。
内容的提问来源于stack exchange,提问作者user3658367
相关产品推荐
相关产品推荐

