|
在处理数据时,有时候会遇见变量值为多选的情况,此时如果要给变量添加上format,就略微麻烦许多。今天分享一段针对此种情况自动生成format的程序。
程序实现效果
先来看看程序实现的效果(如下图),此时定义的是1=张三、2=李四、3=王五。
将这个程序写成了一个简单的宏,下面来看一下生成上面结果的程序。
- %add_multipe_fmt(inds=a,invar=x,dlm=%str(,)
- ,valuelist=%str(1=张三|2=李四|3=王五),orderYn=1,fmtname=testfmt4_);
- data b2;
- set a;
- format x $testfmt4_.;
- run;
复制代码
程序原理
在分享这个程序的原理前,先来看看要设置的那些宏参数以及其作用。
原理:
1.获取变量观测值的种类(去重)
2.根据指定分割符将观测中的值进行拆分(得到一个数据集)
3.根据输入的valuelist生成一个存放单选值及对应format的数据集
4.将上面俩个数据集进行left join ,在进一步组合等操作
5.利用proc format语句生成format
程序:
- %macro add_multipe_fmt(inds=,invar=,dlm=%str(),valuelist=,orderYn=1,fmtname=);
- *获取数据集中观测种类;
- proc sql undo_policy=none;
- create table tmp_ds1 as
- select distinct &invar.; from &inds.;
- quit;
- *将数据集衍生一个行号,并根据分隔符拆分数据;
- data tmp_ds2;
- set tmp_ds1;
- line1=_N_;
- do i=1 to count(strip(&invar;),"&dlm.;")+1;
- line2=i;
- value_s=kscan(strip(&invar;),i,"&dlm.;");
- if index(value_s,'-') then do;
- do _sm_=input(scan(value_s,1,'-'),??best.) to input(scan(value_s,2,'-'),??best.);
- value_s=strip(vvalue(_sm_));
- output;
- end;
- end;
- else output;
- end;
- run;
- /*针对选项值进行一步处理,将宏变量valuelist 存入数据集中(以“|”作为分隔符)*/
- data valuelist;
- length valuelist $20000.;
- format valuelist $20000.;
- informat valuelist $20000.;
- valuelist="&valuelist.;";
- do i=1 to count(strip(valuelist),"|")+1;
- valuelist_s=kscan(strip(valuelist),i,"|");
- valuelist_s1=kscan(valuelist_s,1,"=");
- valuelist_s2=kscan(valuelist_s,2,"=");
- output;
- end;
- run;
- *将选项值进行一个left join ;
- proc sql undo_policy=none;
- create table tmp_ds3 as
- select a.*,b.valuelist_s2
- from tmp_ds2 as a
- left join valuelist as b
- on a.value_s =b.valuelist_s1
- order by line1,line2;
- quit;
- *如果排序 orderYn=1 ;
- %if &orderYn.; eq 1 %then %do;
- proc sort data=tmp_ds3 out=tmp_ds3 sortseq=linguistic(numeric_collation=on);by line1 value_s ;quit;
- %end;
- data tmp_ds4;
- set tmp_ds3;
- by line1 ;
- length final $20000.;
- retain final ;
- if first.line1 then do;
- final=strip(valuelist_s2);
- end;
- else do;
- final=strip(catx("&dlm.;",final,valuelist_s2));
- end;
- fmt=quote(strip(&invar.;))||strip("=")||quote(strip(final));
- if last.line1 then output;
- run;
- proc sql noprint;
- select fmt into:add_fmt separated by " " from tmp_ds4 ;
- quit;
- proc format ;
- value $ &fmtname.; &add;_fmt.;
- run;
- *在日志打印内容;
- %put ********************多选FORMAT:&fmtname.;已生成*********************;
- %put &add;_fmt.;
- proc delete data=work.tmp_ds1 work.tmp_ds2 work.tmp_ds3 work.tmp_ds4;run;
- %mend;
复制代码 |
|