我使用以下代码更改数据集中所有字符变量的长度。我不知道为什么这个循环不起作用。
data test ;
set my.data;
array chars[*] _character_;
%do i = 1 %to dim(chars);
length chars[i] $ 30 ;
%end;
run;
答案 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;
结果变量列表:
这也是一个有用的案例,因为它将演示一个更改字符变量长度的问题。如果您已为变量指定了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;