使用数组将SAS数据集从长格式转宽格式时遇下标越界错误
问题:SAS数组转置长表到宽表时出现"Array subscript out of range"报错
需求:将REDCap导出的长格式数据集转置为宽格式,每个参与者对应一行,把重复表单的c10_formcompletedate拆分为多列(如c10_formcompletedate1、c10_formcompletedate2...)。因需处理多个变量,不想使用PROC TRANSPOSE,尝试用数组实现时触发报错:Array subscript out of range at line 39 column 4。
原代码
proc sort data=bl out=longsrt; by pid; run; data wide; set longsrt; by pid; keep pid c10:; retain c10:; array ac10_formcompletedate{*} c10_formcompletedate; if first.pid then do; do i = 1 to 500; ac10_formcompletedate ( i ) = .; end; end; ac10_formcompletedate( redcap_event_name_bl ) = c10_formcompletedate; if last.pid then output; run;
测试数据集
data bl; input pid redcap_event_name_bl c10_formcompletedate; cards; 10001 baseline 2023-10-18 10001 baseline . 10001 baseline . 10001 baseline 2023-10-19 10002 baseline . 10002 baseline 2023-10-18 10002 baseline 2023-10-18 10003 baseline . 10003 baseline 2023-10-18 ; run;
报错原因分析
- 数组定义错误:原数组
ac10_formcompletedate{*} c10_formcompletedate;仅关联了单个变量,数组长度为1,但后续循环到500,直接触发下标越界。 - 下标逻辑错误:用字符变量
redcap_event_name_bl(值为baseline)作为数组下标,SAS会自动将字符转为数值,结果为缺失值,同样导致下标越界。 - 缺少记录计数变量:没有对每个参与者的重复表单记录进行计数,无法将每条记录对应到数组的不同位置。
修正后的代码
proc sort data=bl out=longsrt; by pid; run; data wide; set longsrt; by pid; /* 定义数组,生成500个用于存储表单日期的变量,可根据实际需求调整长度 */ array ac10_formcompletedate[500] c10_formcompletedate1-c10_formcompletedate500; /* 计数变量,用于标记当前pid的第几条记录 */ retain n; keep pid c10_formcompletedate:; if first.pid then do; n = 0; /* 初始化数组,用dim函数获取数组实际长度,避免硬编码 */ do i = 1 to dim(ac10_formcompletedate); ac10_formcompletedate[i] = .; end; end; n + 1; /* 将当前记录的日期赋值到数组对应位置 */ if n <= dim(ac10_formcompletedate) then do; ac10_formcompletedate[n] = c10_formcompletedate; end; if last.pid then output; run;
代码说明
- 数组
ac10_formcompletedate[500]直接定义了500个变量,覆盖大部分重复记录场景,可根据实际数据的最大重复数调整长度。 - 用
n作为计数变量,在每个pid的第一条记录时重置为0,后续每条记录递增,确保每条表单日期对应到不同的数组下标。 - 初始化数组时使用
dim(ac10_formcompletedate)获取数组长度,避免硬编码带来的下标越界风险。 - 增加了
n <= dim(ac10_formcompletedate)的判断,防止记录数超过数组长度时再次触发报错。
内容的提问来源于stack exchange,提问作者Alessia
相关产品推荐
相关产品推荐

