【问题标题】:How to change the character length for all character variables in SAS?如何更改 SAS 中所有字符变量的字符长度?
【发布时间】:2018-03-06 04:33:36
【问题描述】:

我正在使用以下代码来更改我的数据集中所有字符变量的长度。我不确定为什么这个循环不起作用。

   data test ; 
   set my.data; 
   array chars[*] _character_;
     %do i = 1 %to dim(chars); 
       length chars[i] $ 30  ; 
     %end; 
   run;

【问题讨论】:

    标签: sas


    【解决方案1】:

    一方面,您正在混合使用数据步骤和宏命令。 %do 仅是宏,但其余部分仅是数据步骤。您还需要将length 语句作为第一次 遇到变量,而不是set 语句,因为字符长度在第一次遇到后不可更改。

    您要么需要在宏语言中执行此操作,要么使用其他一些数据驱动的编程技术来执行此操作(正如 user667489 所指的那样)。这里有两种方法。

    基于宏,使用open 函数组,它打开数据集,计算有多少变量,然后遍历这些变量并为每个变量调用长度语句(您可以相同地有一个长度,遍历变量和一个数字)。这适用于通用宏,但可能更难维护。

    %macro make_class_longer(varlength=);
    data class;
      %let did=%sysfunc(open(sashelp.class,i));
      %let varcount=%sysfunc(attrn(&did,nvars));
      %do _i = 1 %to &varcount;
        %if %sysfunc(vartype(&did., &_i.))=C %then %do;
          length %sysfunc(varname(&did.,&_i)) $&varlength.;
        %end;
      %end;
      %let qid=%sysfunc(close(&did));
    
      set sashelp.class;
    run;
    %mend make_class_longer;
    
    %make_class_longer(varlength=30);
    

    同样,这里有一个dictionary.columns 解决方案。这直接查询元数据并在宏变量中构建字符变量列表,然后在正常长度语句中使用该列表。更容易维护,可能更慢(但大多是没有意义的)。

    proc sql;
      select name into :charlist separated by ' '
      from dictionary.columns
      where libname='SASHELP' and memname='CLASS' and type='char'
      ;
    quit;
    
    data class;
      length &charlist. $30;
      set sashelp.class;
    run;
    

    【讨论】:

      【解决方案2】:

      变量的长度是在编译数据步时确定的,所以第一个提到变量的语句通常会确定它的长度。在您的示例中,这是 set 语句。一旦固定,变量的长度就不能改变,除非你重建整个数据集。

      要在此处获得所需的结果,您需要将 length 语句移到 set 语句上方,因此您还需要明确指定要设置其长度的变量的所有名称,因为在编译期间它们将不存在。您可以通过硬编码或从sashelp.vcolumn / dictionary.columns 生成代码来做到这一点。

      【讨论】:

        【解决方案3】:

        该代码中有许多逻辑和语法错误。

        主要的逻辑错误是在 SAS 已经确定字符变量的长度后,您无法更改它的长度。在您的代码中,它是在编译 SET 语句时确定的。

        另一个逻辑错误是在数据步骤中使用宏 %DO 循环。为什么?

        您的示例 LENGTH 语句在语法上是错误的。 LENGTH 语句中不能有数组引用。只是实际的变量名称。您可以在 ARRAY 语句中设置长度,如果它是定义变量的第一个位置。但是您不能使用_character_ 变量列表,因为变量列表要查找变量,必须已经定义变量。这意味着改变为时已晚。

        您可能需要恢复到少量代码生成。

        让我们使用 PROC IMPORT 创建一个示例数据集。我们可以为此使用 SASHELP.CLASS 示例数据。

        filename csv temp;
        proc export data=sashelp.class outfile=csv dbms=csv ;run;
        proc import datafile=csv out=sample replace dbms=csv ;run;
        

        结果变量列表:

        这也是一个有用的案例,因为它将演示一个关于更改字符变量长度的问题。如果您已将 FORMAT 分配给变量,则最终变量长度可能与格式宽度不匹配。

        这是一种动态生成代码以更改字符变量长度的方法而不更改它们在数据集中的相对位置。基本上这将读取表的元数据并使用它为每个变量生成一系列名称/类型+长度对。

        proc sql noprint ;
          select varnum
               , catx(' ',name,case when type='num' then put(length,1.) else '$30' end)
            into :varlist
               , :varlist separated by ' '
          from dictionary.columns 
          where libname='WORK' and memname='SAMPLE'
          order by 1
          ;
        quit;
        

        然后您可以在LENGTH 语句中使用生成的列表来定义变量的类型和长度。您还可以添加 FORMAT 和 INFORMAT 语句以删除 $xx. 格式和 PROC IMPORT(错误地)添加到字符变量中的信息。

        data want ;
          length &varlist ;
          set sample;
          format _character_ ;
          informat _character_;
        run;
        

        【讨论】:

        • 这是有道理的。我是 stata 用户,所以 sas 一开始并不直观。但是这个解释对我来说非常有用。非常感谢。
        猜你喜欢
        • 2017-09-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-16
        • 2018-03-04
        • 2013-12-19
        相关资源
        最近更新 更多