如何更改SAS中所有字符变量的字符长度?

时间:2018-03-05 16:17:20

标签: sas

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

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

3 个答案:

答案 0 :(得分:0)

变量的长度是在编译数据步骤时确定的,因此提及变量的第一个语句通常决定其长度。在您的示例中,这是set语句。修复后,除非重建整个数据集,否则无法更改变量的长度。

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

答案 1 :(得分:0)

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

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

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

%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 :(得分:0)

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

主要的逻辑错误是,在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;

结果变量列表:

enter image description here

这也是一个有用的案例,因为它将演示一个更改字符变量长度的问题。如果您已为变量指定了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;

enter image description here