浮光掠影转瞬间 发表于 2019-7-12 15:41:54

实现多选值FORMAT的添加


在处理数据时,有时候会遇见变量值为多选的情况,此时如果要给变量添加上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
selecta.*,b.valuelist_s2
fromtmp_ds2as a
left joinvaluelistas 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_ds3out=tmp_ds3sortseq=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;
页: [1]
查看完整版本: 实现多选值FORMAT的添加