|
楼主

楼主 |
发表于 2011-4-18 17:03:59
|
只看该作者
怎样批量将纯数字的字符变量转化为数值型变量而不会转化含非数字的变量
论坛上有关于将字符变量转化为数字变量的宏或语言,我自己也写了一个简单的:[code:yvv0jpw1]%macro numberic(data= ,svar= ,out=&data );
data &out;
set &data;
%let i = 1;
%let var = %scan(&svar, &i);
%do %while(&var ne);
%let i= %eval(&i+1);
%let var = %qscan(&svar, &i);
%end;
%let i=%eval(&i-1);
%do j=1 %to &i;
%let e=%scan(&svar,&j);
&e=compress(&e);
%let e1=&e.1;
&e1=&e*1;
drop &e;
rename &e1=&e;
%end;
run;
%mend;
%numberic(data=b,svar=glu ins homair lhomair glu2 ins2 hgb ma1 crea u_crea alb bun acr eccr egfr lacr alt ast ggt tg chol hdl ldl lpa apoa1 apob ghb,out=ff);
[/code:yvv0jpw1]该红只要将需要转化的变量加到svar中就可以了。但是有两个问题:
1.我的数据库中有200多个字符变量,光加变量名就得麻烦死。
2.字符型变量中还有许多不是纯数字的,如姓名地址医院等,还有些化验结果不能简单*1了事,如部分为“<0.02”,
我上网上查了一下基本是不管三七二十一全部转化的。
我有个思路:
1.取出所有的字符变量。
2.将变量名赋值给宏变量。
[color=Red:yvv0jpw1]3.如果原变量值不空而将每个字符变量去掉数字和小数点,只剩下空变量则该变量为纯数字变量,如果变量中有一个观测中压缩后不为空则为字符变量。
4.将数值变量进行转化,字符变量不便。[/color:yvv0jpw1]5.将转化后的变量按原顺序排列。
我写了一个极没效率的,不但时间长好像太多变量反倒出错了。
编码如下:[code:yvv0jpw1]data c;
set d.c;run;
%macro d(data=,out=&data);
/*宏功能找出所有的字符变量并将其转化为数值变量,data为需转换的数据集名,out是转换后的数据集名,不指定默认替换原始数据集。 */
%let data=%upcase(&data);
%let a=%scan(&data,1,'.');
%let b=%scan(&data,2,'.');
%if &b= %then %do;
%let a=WORK;
%let b=&data;
%let data=WORK.&b;
%end;/*分别取库名及数据集名称,a为库名,b为集名*/
data _TMP_;
set &data;
run;/*保留原始数据集,特别是在out不等于data时,保留原始数据在工作中很重要。*/
proc sql noprint ;
select upcase(name) into :var separated by ' '
from dictionary.columns
where libname="&a" and memname="&b";
quit;
/*取原始数据中变量的顺序,将变量依照原始顺序存入宏变量var。使转换后仍按此顺序排列*/
proc sql ;
create table char as
select * from &data (keep= _character_ );
run;/*取原始数据集中所有字符变量组成数据集*/
proc contents data=char position out=content(keep=name varnum) noprint;
run;/*取字符型数据集中变量名*/
proc sort data=content;
by varnum;
proc sql noprint;
select name into: name separated by ' '
from content order by varnum;
select 'T_'||compress(name)||'_1' into: name_1 separated by ' '
from content order by varnum;
select 'T_'||compress(name)||'_2' into: name_2 separated by ' '
from content order by varnum;
quit;/*将字符型数据集中的变量名按序存入name宏变量,同时产生两列新变量用于存放中间结果*/
%let dropn=;
%let dropc=;
%let renan=;
%let n=0;
%do i=1 %to &sqlobs ;
%let cha=%scan(&name,&i);
%let num=%scan(&name_1,&i);
%let r1=%scan(&name_2,&i);
DATA _Tmp_/*(drop=i _C_)*/;
set _TMP_;
if compress(&cha)='' then &r1+0;
else do;
if compress(&cha,'.','d')='' then &r1+0;else &r1+1;
end;
if &r1=0 then do;
&num=&cha-0;
call symput('dropn',"&dropn."||" "||"&cha.");
call symput('renan',"&renan."||" "||"&num.");
call symput('n',%eval(&n+1));
end;
if &r1>0 then do;
call symput('dropc',"&dropc."||" "||"&num.");
end;
RUN;
%end;
data &out;
set _TMP_(drop=&dropc &name_2);
%do s=1 %to &n;
%let cha=%scan(&dropn,&s);
drop &cha;
%let num=%scan(&renan,&s);
rename &num=&cha;
%end;
run;
data &out;
retain &var;
set &out;
run;
proc delete data=char content _tmp_;
run;
%mend;%d(data=d.jd);
[/code:yvv0jpw1]主要麻烦是第三步第四步中怎样保证数字型字符变量转而其他的不转换 |
|