能否使用数组处理在SAS中转换数据集并新增动态分类列?
SAS数据集长转宽的数组实现方案
要实现从原长格式数据集到目标宽格式的转换,结合你已定义的宏变量和数组框架,可按以下步骤完成代码编写:
核心思路
- 提取原
Name字段的前缀(如Cost_1中的Cost)作为新的Name值,提取后缀数字作为数组索引; - 利用
retain语句保持数组值跨观测不重置,积累同组数据; - 按新
Name分组,每组最后一条观测时输出结果并重置数组。
完整代码
%let Cat_Count = 2; /* 若原数据集同组观测不连续,先执行排序(可选) */ proc sort data=a; by scan(Name, 1, '_'); run; data b; length Name $20; /* 定义新Name变量的长度,匹配原数据需求 */ /* 重命名原Name变量为_Name_,避免与新生成的Name冲突 */ set a(rename=(Name=_Name_)); /* 定义目标数组,对应cat_1到cat_&Cat_Count */ array category[&Cat_Count] cat_1-cat_&Cat_Count; /* 保持数组值,跨观测保留数据 */ retain cat_1-cat_&Cat_Count; /* 提取前缀作为新Name */ Name = scan(_Name_, 1, '_'); /* 提取后缀数字,转为数值型作为数组索引 */ cat_num = input(scan(_Name_, 2, '_'), 8.); /* 将当前Value赋值到对应数组位置 */ if cat_num in 1:&Cat_Count then do; category[cat_num] = Value; end; /* 按新Name分组,处理每组最后一条观测 */ by Name; if last.Name then do; output; /* 输出当前组的结果 */ call missing(of category[*]); /* 重置数组,准备下一组 */ end; /* 删除临时变量,清理数据集 */ drop _Name_ cat_num Value; run;
代码说明
- 重命名原变量:将原
Name改为_Name_,避免新生成的Name覆盖原数据,保证前缀和序号提取正常。 - 数组与retain:
retain语句确保数组值不会在每次读取新观测时被重置,实现同组数据的积累。 - 分组输出:通过
by Name和last.Name判断每组的结束,此时输出整理好的宽格式数据,并重置数组避免影响下一组。 - 临时变量清理:
drop语句移除过程中生成的临时变量,得到目标结构的数据集。
注意事项
- 若原数据集的
Value字段同时包含数值和字符类型(如示例中的28、Fixed),需确保原数据集的Value为字符型,否则数值型变量会导致字符值缺失。 - 若原数据集同组观测(如
Cost_1、Cost_2)是连续排列的,可省略排序步骤,将by Name改为by Name notsorted。
内容的提问来源于stack exchange,提问作者B K
相关产品推荐
相关产品推荐

