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

问题描述 投票:0回答:3

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

   data test ; 
   set my.data; 
   array chars[*] _character_;
     %do i = 1 %to dim(chars); 
       length chars[i] $ 30  ; 
     %end; 
   run;
sas
3个回答
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;

0
投票

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

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


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

© www.soinside.com 2019 - 2024. All rights reserved.