Dataset: Have
F1 F2
Student Section
Name No
数据集"有"。数据有新的线条特征。
我需要从数据中压缩换行符。
我想动态地这样做,因为有时"有"数据集可能包含新变量,如F3,F4,F5 etc.
,
我已经写了宏来做这个..但它没有按预期工作。
当我执行下面的代码时,第一次我收到错误作为无效的引用newcnt。如果我在同一个会话中第二次执行,我没有收到错误。
PFB我的代码:
%macro update_2(newcnt);
data HAVE;
set HAVE;
%do i= 1 %to &newcnt;
%let colname = F&i;
&colname=compress(&colname,,'c');
%end;
run;
%mend update_2;
%macro update_1();
proc sql noprint;
select count(*) into :cnt from dictionary.columns where libname="WORK" and memname="HAVE";
quit;
%update_2(&cnt)
%mend update_1;
注意:所有变量的名称都为F1,F2,F3,F4.
,
请告诉我出了什么问题..
如果还有其他程序,请帮助我。
答案 0 :(得分:3)
在您的宏%update_1
中,您创建了一个名为&cnt
的宏变量,但是当您调用%update_2
时,您会引用另一个宏变量&colcnt
。尝试修复此引用,看看您的代码是否按预期运行。
答案 1 :(得分:2)
我们创建了自己的函数,使用proc fcmp
从字符串中清除不需要的字符。在这种情况下,我们的函数会清除制表符,换行符和回车符。
proc fcmp outlib=common.funcs.funcs; /* REPLACE TARGET DESTINATION AS NECESSARY */
function clean(iField $) $200;
bad_char_list = byte(10) || byte(9) || byte(13);
iCleaned = translate(iField," ",bad_char_list);
return (iCleaned );
endsub;
run;
使用中间的新行字符创建一些测试数据,然后将其导出并查看结果。您可以看到字符串已跨行分割:
data x;
length employer $200;
employer = cats("blah",byte(10),"diblah");
run;
proc export data=x outfile="%sysfunc(pathname(work))\x.csv" dbms=csv replace;
run;
对字符串运行新创建的clean()
函数并再次导出。您可以根据需要看到它现在在一行上:
data y;
set x;
employer = clean(employer);
run;
proc export data=y outfile="%sysfunc(pathname(work))\y.csv" dbms=csv replace;
run;
现在将此方法应用于我们所需数据集中的所有字符变量。不需要宏,只需定义一个引用所有字符变量的数组,然后在应用clean()
函数时迭代它们:
data cleaned;
set x;
array a[*] _char_;
do cnt=lbound(a) to hbound(a);
a[cnt] = clean(a[cnt]);
end;
run;
编辑:另请注意,fcmp可能需要考虑一些性能问题。如果您正在处理大量数据,可能会有其他解决方案表现更好。
答案 2 :(得分:2)
以下是Robert Penridge函数的示例,作为以数组作为参数的调用例程。这可能仅适用于9.4+或更高版本的9.3,当永久数组开始被允许以这种方式用作参数时。
我不确定这是否可以通过数组作为函数灵活地完成;不使用宏(需要不断重新编译函数)我不知道如何在不将其作为调用例程的情况下返回正确的数组大小。
我在下拉列表中添加了“Z”,因此很明显它可以正常工作。
options cmplib=work.funcs;
proc fcmp outlib=work.funcs.funcs;
sub clean(iField[*] $);
outargs iField;
bad_char_list = byte(11)|| byte(10) || byte(9) || byte(13)||"Z";
do _i = 1 to dim(iField);
iField[_i] = translate(iField[_i],trimn(" "),bad_char_list);
end;
endsub;
quit;
data y;
length employer1-employer5 $20;
array employer[4] $;
do _i = 1 to dim(employer);
employer[_i] = "Hello"||byte(32)||"Z"||"Goodbye";
end;
employer5 = "Hello"||byte(32)||"Z"||"Goodbye";
call clean(employer);
run;
proc print data=y;
run;
答案 3 :(得分:1)
这是另一种选择。如果你想要删除换行符,那么我们只讨论Char,你可以利用隐式数组和Do over,
data want;
set have;
array chr _character_;
do over chr;
chr=compress(chr,,'c');
end;
run;