You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于子串提取创建变量实现SAS数据集转置需求问询

解决SAS数据集按规则转置提取字段的问题

现有SAS数据集需按特定规则转置:原数据集包含ID及75个NT开头的变量,其中待处理的notes类变量后缀为奇数(如nt3、nt5等)。目标是转置后按ID拆分出time、date、code、notes字段,每个ID对应多条记录,以下是详细信息及解决方案。

原数据集代码

data have;
    input ID $1. NT2 $38. NT3 $4. NT4 $38. NT5 $4.;
    cards;
1   NOTES 12:13:44 03-16-2018 CODE: ABC AML  NOTES 09:13:11 03-12-2018 CODE: OPI TEST
2   NOTES 04:25:09 01-04-2018 CODE: FDS IMD  NOTES 03:25:10 01-09-2018 CODE: FGH TEST
3   NOTES 12:22:49 11-12-2018 CODE: DGH TEST NOTES 08:02:49 11-11-2018 CODE: LKO AML
4   NOTES 22:02:21 01-14-2018 CODE: MKL TEST NOTES 07:02:21 01-10-2018 CODE: LOP IMD
5   NOTES 09:01:36 01-23-2018 CODE: HJK TEST NOTES 09:01:56 01-23-2018 CODE: UIY TEST
;
run;

期望输出

IDtimedatecodenotes
112:13:4403-16-2018ABCAML
109:13:1103-12-2018OPITEST
204:25:0901-04-2018FDSIMD
203:25:1001-09-2018FGHTEST
312:22:4911-12-2018DGHTEST
308:02:4911-11-2018LKOAML
422:02:2101-14-2018MKLTEST
407:02:2101-10-2018LOPIMD
509:01:3601-23-2018HJKTEST
509:01:5601-23-2018UIYTEST

现有代码问题分析

用户编写的代码无法得到目标输出,核心问题包括:

  • 数组t包含所有NT开头变量,未筛选后缀为奇数的目标变量
  • 提取字段时错误引用nt0,未使用当前循环的数组元素t[_i]
  • 未在循环内执行output,导致每个ID仅保留最后一次循环结果
  • note0的拼接逻辑与需求无关,属于冗余代码

现有错误代码:

data note11;
 length note0 $50;
 set note10;

  array t{*} nt:;;
    do _i = 1 to dim(t);
/*确保notes非空*/
      if not missing(t[_i]) then note0 = catx('/',note0,vname(t(_i)));
/*提取时间戳、日期、代码*/
      if find(upcase(t[_i]),"NOTES") then do;
     timestamp=substr(left(nt0), index(left(nt0), 'NOTES')+5, 9);                                                                                                              
         date=substr(left(nt0), 15, 10);  
         code = substr(left(nt0), index(left(nt0), 'CODE:')+5);     
      end;

    end;
   drop _i;
run;

解决方案代码

以下代码可实现目标需求,适配75个NT变量的场景:

data want;
    set have;
    /* 定义数组包含所有NT开头变量 */
    array nt_all{*} nt:;
    do _i = 1 to dim(nt_all);
        /* 提取变量名后缀的数字 */
        _suffix = input(scan(vname(nt_all[_i]), 2, 'NT'), best.);
        /* 仅处理后缀为奇数且非空的变量 */
        if mod(_suffix, 2) = 1 and not missing(nt_all[_i]) then do;
            /* 提取time:NOTES后的第一个字段 */
            time = scan(nt_all[_i], 2, ' ');
            /* 提取date:NOTES后的第二个字段 */
            date = scan(nt_all[_i], 3, ' ');
            /* 提取CODE:后的内容,拆分code和notes */
            _code_str = substr(nt_all[_i], index(upcase(nt_all[_i]), 'CODE:') + 5);
            code = scan(_code_str, 1, ' ');
            notes = scan(_code_str, 2, ' ');
            /* 输出当前记录 */
            output;
        end;
    end;
    /* 丢弃临时变量和原始NT变量 */
    drop _i _suffix _code_str nt:;
run;

代码要点说明

  1. 变量筛选:通过提取变量名后缀的数字,用mod(_suffix,2)=1判断是否为奇数,无需手动枚举75个变量
  2. 字段提取:使用scan和index函数替代固定位置截取,避免因字符串长度变化导致的提取错误
  3. 记录生成:每次循环符合条件时执行output,为每个ID生成多条对应记录
  4. 清理冗余:最后丢弃临时变量和原始NT变量,仅保留目标字段

内容的提问来源于stack exchange,提问作者lydias

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 07:55:25