SAS 32字符列名称问题

时间:2018-07-10 19:25:33

标签: sas sas-macro

我试图通过重命名列的名称(因为它们来自其来源)来遵守对32个字符的限制。问题是,通过使用数据步骤(如下),我收​​到“错误23-322:变量名称长于32个字符”的错误。

这就是我要使用的:

    data mydata;
    set mydata;
        rename Thisisthelongcolumnnamefromthesourcetable = ShorterName;
    run;

我听说使用ds2可以解决此问题,但是使用ds2进行的每次尝试都给了我类似的错误。由于我无法直接控制源数据,因此有没有针对此限制的解决方法?

此外,似乎SAS会自动截断列的名称,但是“标签名称”仍为实际长度。有没有办法通过引用列名来更改列名?

谢谢您的帮助!

2 个答案:

答案 0 :(得分:1)

可以编写一个“内联宏”来为您生成重命名选项。 “内联宏”是一种不会发出导致执行步骤边界的SAS代码的宏-该宏将执行处理并发出SAS代码片段,该片段可用作其他SAS语句的一部分。

考虑带有签名的宏

%renameByLabel(data=, byvarname=allow, rename=(label-1=newname-1 label-2=newname-2)).

该宏将打开数据集,检查每个变量的名称和标签,并尝试将它们与label=name参数中列出的rename=对之一进行匹配。

使用此类宏可用于处理此代码所需的重命名操作

data have;
  x12345=1;            label x12345="This is x";
  ___y__scrap = "ABC"; label ___y__scrap="This is y";
  ageold = 7;          label ageold="Old age";
run;

data want;
  set have (%renameByLabel(data=have,rename=("This is x"=x "This is y"=y ageold=age)));
run;

Macro无法访问当前执行程序标记化流,因此无法知道当前语句将要处理的数据集。宏要求使用data=明确声明要处理的数据集(即使内联调用结果是set语句的一部分)

示例宏

%macro renameByLabel(data=, byvarname=allow, rename=) / parmbuff;

  %local allow ds nvar ri i rename varlabel varname L pair lhs rhs result pairename;
  %let allow = %upcase(%superq(byvarname));

  %let ds = %sysfunc(open(&data));
  %if &ds %then %do;

    %if %index(&ds,%str(%()) %then 
      %put WARNING: &SYSMACRONAME does not like KEEP= or DROP= options;

    %let nvar = %sysfunc(attrn(&ds, nvar));

    %let L = %length(%superq(rename));
    %if "%substr(%superq(rename),&L,1)" = ")" %then %let rename=%substr(%superq(rename),1,%eval(&L-1));

    %let L = %length(%superq(rename));
    %if "%substr(%superq(rename),1,1)" = "(" %then %let rename=%substr(%superq(rename),2,%eval(&L-1));

    %let L = %length(&rename);
    %do ri = 1 %to &L;
      %let pair = %scan(%superq(rename),&ri,%str( ),Q);

      %if %length (&pair) %then %do;

        %let lhs = %scan(%superq(pair),1,=,Q);
        %let rhs = %scan(%superq(pair),2,=,Q);
        %let pairename =;

        %do i = 1 %to &nvar;
          %let varname = %sysfunc(varname(&ds,&i));
          %let varlabel = %sysfunc(varlabel(&ds,&i));

          %if %superq(varlabel) = %superq(lhs) or
             "%superq(varlabel)" = %superq(lhs) 
          %then %do;
            %let pairename = &varname=&rhs;
            %let i = &nvar;
          %end;

          %if &allow=ALLOW %then %do;
            %if &varname = %superq(lhs) or
               "&varname" = %superq(lhs)
            %then %do;
              %let pairename = &varname=&rhs;
            %end;
          %end;
        %end;

        %let result = &result &pairename;

      %end;
      %else
        %let ri = &L;

    %end;

    %let ds = %sysfunc(close(&ds));

    %* emit the generated rename option in-line;
    rename=(&result)
    %put NOTE: Generated rename option is %superq(result);
  %end;
  %else
    %put ERROR: Could not open data=%superq(data);

%mend;

宏测试

* test 1;
%put %renameByLabel (data=sashelp.class, varname=Allow, rename=("Name"=NewName Age=NewAge));

* ===log===;
* NOTE: Generated rename option is rename=(Name=NewName Age=NewAge);

* test 2;
data have;
  x12345=1; label x12345="This is x";
  ___y__scrap = "ABC"; label ___y__scrap="This is y";
  ageold = 7; label ageold="Old age";
run;

data want;
  set have (%renameByLabel(data=have,rename=("This is x"=x "This is y"=y ageold=age)));
run;

* ===log===;
* NOTE: Generated rename option is rename=(x12345=x ___y__scrap=y ageold=age)

在旁边

需要进行一些小的更改才能使宏仅发出重命名对,因此可以将其用作数据集rename=()选项的一部分,或用作rename语句的一部分。

您可以将宏重写为Proc DS2函数,例如说myRenameByLabel,然后用%sysfunc(myRenameByLabel(…))调用该函数。有时,在DS2语句中处理异常的引用和取消引用情况会更容易。

答案 1 :(得分:0)

您尝试过以下吗?

data mydata;
set mydata (rename=(Thisisthelongcolumnnamefromthesourcetable = ShorterName));   
run;

SAS正在SET语句中进行变量命名。由于您直到SET语句完成后才尝试使用RENAME函数,因此为时已晚。如上所示,将RENAME用作SET语句选项,可以在SET读取变量之前重命名该变量。