寫在前面第美。
最近的兩篇文章分別介紹了我編寫下面這兩個(gè)宏時(shí)整體的思路和方法增显。菜鳥小白一枚,很歡迎有大佬能夠閱讀并批評(píng)指點(diǎn)拿霉。
SAS編程實(shí)踐---宏:按系統(tǒng)術(shù)語、首選術(shù)語和嚴(yán)重程度分層次計(jì)算受試者發(fā)生不良反應(yīng)(AE)例數(shù)和例次
SAS編程實(shí)踐---宏:按系統(tǒng)術(shù)語和首選術(shù)語分層次計(jì)算受試者發(fā)生不良反應(yīng)(AE)例數(shù)和例次
文章中呈現(xiàn)的是最終的宏代碼咱扣,但是在實(shí)際編寫過程中绽淘,步驟順序
可能會(huì)和文章的結(jié)構(gòu)順序不同,畢竟寫文章和寫代碼還是有區(qū)別的
闹伪。
代碼編寫時(shí)可能會(huì)經(jīng)歷沪铭,編寫---替換修改---增添---替換修改---...
,這樣的步驟很多次才形成了最終的代碼偏瓤。
不過目前我堅(jiān)持的編寫宏程序的總體結(jié)構(gòu)
還是如之前的文章一樣杀怠,也即:
*_1. pre-processing;
*_2.main statistical steps;
*_3 processing step of stat;
* _4.output steps;
- 預(yù)處理(宏變量的處理和輸入數(shù)據(jù)集的預(yù)處理)
- 主要的統(tǒng)計(jì)步驟
- 統(tǒng)計(jì)步驟后的處理
- 輸出步驟
基本原則
在實(shí)際操作中,最開始進(jìn)行目標(biāo)表格拆解分析
和模擬數(shù)據(jù)生成
后厅克,進(jìn)行到宏程序代碼編寫步驟驮肉,會(huì)先進(jìn)行上述第1步中的輸入數(shù)據(jù)集的預(yù)處理
和第2步的統(tǒng)計(jì)步驟
。
這兩步是處理數(shù)據(jù)的最核心的步驟已骇,而其他的步驟离钝,更多是為了進(jìn)行表格拼接修改
,使達(dá)到目標(biāo)表格樣式
褪储;或者基于SAS宏的”文本替換“
原則進(jìn)行的輔助步驟卵渴。
- 說明一下,很多步驟使用
PROC SQL
語句會(huì)簡單許多鲤竹,但是本文中除了少量的宏變量的賦值會(huì)使用PROC SQL
語句以外浪读,還是以使用基礎(chǔ)DATA
步和過程步
為主昔榴。
準(zhǔn)備步驟
說了這么多,下文我便一步一步實(shí)踐去編寫一個(gè)”基本描述性統(tǒng)計(jì)量表格“
的宏的編寫碘橘。
目標(biāo)表格拆解分析
圖中是將要生成的目標(biāo)表格的模板:
指明了
數(shù)值型變量
互订,進(jìn)行核心統(tǒng)計(jì)步proc means
需要計(jì)算的統(tǒng)計(jì)指標(biāo)有哪些;需要注意nminssing
痘拆,可能存在分析數(shù)據(jù)集里觀測(cè)的缺失
仰禽,所以我一般使用adsl
數(shù)據(jù)集進(jìn)行各組受試者數(shù)量的確定;表明了
在拼接步需要拼接成的樣式
纺蛆,需要注意吐葵,小數(shù)點(diǎn)位數(shù)的保留問題
,因此需要在核心步驟之外進(jìn)行小數(shù)點(diǎn)位數(shù)保留問題的處理桥氏;合計(jì)列是否計(jì)算
温峭,需要條件選擇語句
,以及相應(yīng)的數(shù)據(jù)預(yù)處理和計(jì)算步驟字支;指明了
分組
凤藏,分組變量是必須存在的
,且我一般盡量會(huì)處理為數(shù)值型
堕伪。
模擬數(shù)據(jù)生成
通過目標(biāo)表格的拆解揖庄,明確了那些模擬數(shù)據(jù)需要那些變量。
分析數(shù)據(jù)集
分析數(shù)據(jù)集
必須要包含了分組變量
和待統(tǒng)計(jì)分析的數(shù)值型變量
刃跛。
我使用如下代碼生成模擬數(shù)據(jù):
%let seed1 = 33333333;
data ad0;
do ii = 1 to 3;
armn = ii;
arm = cats("第",put(ii, best.) ,"組");
do jj = 1 to 100;
usubjid = cats( "X",put(ii, best.) ,"-", put(jj, z3.));
if mod(jj,3) = 0 then
SEX = "女";
else SEX = "男";
HEIGHT = round(ranuni(&seed1.)*30 + 155, 0.1);
output;
end;
end;
run;
同時(shí)抠艾,人為地造成了若干條觀測(cè)的缺失
:
data ad;
set ad0;
if jj in (2 13 17) and sex = "男" then
delete;
if jj in (12 7 24) and sex = "女" then
delete;
run;
adsl數(shù)據(jù)集
adsl
數(shù)據(jù)集主要用來計(jì)算受試者的數(shù)量
,需要包含分組變量信息
桨昙;
data adsl;
do ii = 1 to 3;
armn = ii;
arm = cats("第",put(ii, best.) ,"組");
do jj = 1 to 100;
usubjid = cats( "X",put(ii, best.) ,"-", put(jj, z3.));
output;
end;
end;
run;
宏編寫步驟
模擬數(shù)據(jù)有了检号,明確了所需的統(tǒng)計(jì)指標(biāo),接下來就是先使用模擬數(shù)據(jù)把數(shù)據(jù)預(yù)處理
和統(tǒng)計(jì)的步驟
寫出來蛙酪,生成目標(biāo)表格
齐苛。
數(shù)據(jù)預(yù)處理和核心統(tǒng)計(jì)步驟
分組統(tǒng)計(jì)
- 我們這個(gè)例子是進(jìn)行身高的描述性統(tǒng)計(jì),使用
proc means
根據(jù)分組變量統(tǒng)計(jì)HEIGHT
桂塞;
* _2.main statistical steps; ;
* _2.1 Calculation of target variable statistics;
* _2.1.1 by group ;
* _2.1.1.1 target variable;
proc means data=ad noprint ;
var HEIGHT;
by armn ;
output out=_bygrpm0 N= n nmiss=nmiss mean=mean STD=std median = mid q1=q1 q3= q3 max=max min=min;
run;
- 分組統(tǒng)計(jì)
adsl
數(shù)據(jù)集中受試者的數(shù)量,為了計(jì)算nmissing
指標(biāo)凹蜂;
* _2.1.1.2 Calculation of the number of every group;
proc freq data=adsl ;
table armn / out=_bygrpnum;
run;
注意,這一步也可以使用proc sql進(jìn)行計(jì)算然后賦值為宏變量會(huì)更加簡單阁危。
- 合并上述兩個(gè)數(shù)據(jù)集
* _2.1.1.3 combine ;
proc sort data=_bygrpm0; by armn;run;
data _bygrp;
merge _bygrpm0
_bygrpnum(drop = percent);
by armn;
run;
分組統(tǒng)計(jì)目標(biāo)變量到這里其實(shí)都準(zhǔn)備好了玛痊。
合計(jì)列
接下來是合計(jì)列指標(biāo)的計(jì)算;
- 合計(jì)數(shù)據(jù)的預(yù)處理
*_1. pre-processing;
* _1.2.1 for sum column ;
data _adsum;
set ad;
armn = 999;
arm = "合計(jì)";
run;
data _adslall;
set adsl;
armn = 999;
arm = "合計(jì)";
run;
- 合計(jì)列統(tǒng)計(jì)量的計(jì)算
* _2.main statistical steps; ;
* _2.2 Calculation of sum column statistics;
* _2.2.1 Calculation of sum column of target variable statistics;
proc means data=_adsum noprint ;
var HEIGHT;
by armn;
output out=_summ0(drop=_TYPE_) N= n nmiss=nmiss mean=mean STD=std median = mid q1=q1 q3= q3 max=max min=min;
run;
- 受試者總數(shù)狂打,為了構(gòu)建nmissing
* _2.2.2 Calculation of number of all subject;
proc freq data=_adslall noprint;
table armn / out=_sumnum;
proc sort ; by armn;
run;
- 合并上述兩個(gè)數(shù)據(jù)集
* _2.2.3 combine ;
proc sort data=_summ0; by armn;run;
data _sum;
merge _summ0
_sumnum(drop = percent);
by armn;
run;
統(tǒng)計(jì)后處理-數(shù)據(jù)拼接
接下來的步驟擂煞,我一般會(huì)這樣做,根據(jù)橫向排列的統(tǒng)計(jì)量趴乡,使用字符拼接函數(shù)拼成所需的樣式对省,然后使用proc transpose
進(jìn)行重新的塑型生成目標(biāo)樣式
蝗拿。
不過為了簡便些,可以先把分組統(tǒng)計(jì)的和最后的合計(jì)列數(shù)據(jù)集先set
蒿涎,然后再進(jìn)行后續(xù)步驟哀托,在宏代碼里,就涉及到條件判斷了劳秋。文章中為了分步展示仓手,我先賦值個(gè)宏變量(包裝進(jìn)宏時(shí)刪除就好),拆開步驟單獨(dú)展示俗批。
判斷是否計(jì)算合計(jì)列的宏參數(shù)我預(yù)設(shè)為rowsumyn
俗或,為了提醒自己市怎,我會(huì)在日志中產(chǎn)生一個(gè)警告
:
%let rowsumyn = Y;
* _3 processing step of stat;
* _3.1 processing step of stat;
%if %sysfunc(upcase(&rowsumyn.)) = %str(Y) %then %do;
%put WARNING: 將計(jì)算合計(jì)列;
data _dt4comb;
set _bygrp
_sum;
run;
%end;
%else %do;
%put WARNING: 不計(jì)算合計(jì)列;
data _dt4comb;
set _bygrp;
run;
%end;
- 接下來是拼接步驟
* _3.2 Variable construction of the target format;
data _combdt;
length _1nnmiss _2meansd _3median _4q1q3 _5minmax $200.;
set _dt4comb;
_1nnmiss =cats( strip(put(n ,8.0)) , "(",strip(put(count - n , 8.0)), ")");
_2meansd = cats( strip(put( round(mean , 0.01 ), 8.2) ) , "(" ,strip(put( round(std, 0.001), 8.3) ) , ")");
_3median = cats( strip(put( round(mid , 0.01 ) , 8.2) ) );
_4q1q3 = cats( strip(put( round(q1 , 0.01 ) , 8.2) ) , "~" ,strip(put( round(q3 , 0.01 ) , 8.2) ) );
_5minmax = cats( strip(put( round(min , 0.01 ) , 8.1) ) , "~" ,strip(put( round(max , 0.01 ) , 8.1) ) );
keep armn _1nnmiss _2meansd _3median _4q1q3 _5minmax;
proc sort; by armn;
run;
注意岁忘,這個(gè)步驟的代碼是初步的,因?yàn)檫@里是硬性規(guī)定了位數(shù)的取舍区匠,而實(shí)際上干像,是還有一步關(guān)于小數(shù)位數(shù)問題的宏變量的預(yù)處理
。
統(tǒng)計(jì)后處理-數(shù)據(jù)塑形
- 之后通過
2次數(shù)據(jù)塑形
驰弄,形成目標(biāo)表格的樣式
* _3.3 transpose;
proc transpose data=_combdt out=_trans1;
var _1nnmiss _2meansd _3median _4q1q3 _5minmax;
by armn;
proc sort; by _NAME_ ;
run;
proc transpose data=_trans1 out=_trans2 prefix= _grp;
id armn;
var col1;
by _NAME_ ;
run;
如下圖所示:
可以看到麻汰,和目標(biāo)表格基本上只有細(xì)節(jié)上的差別的,這些差別的處理就是一些輔助步驟要解決的問題了戚篙。
替換并包裝成宏
宏參數(shù)及替換
接下來就是確定宏參數(shù)名稱五鲫,這個(gè)宏我限定如下這些參數(shù):
%macro MeanT(
libin=,
dtin=,
adsl=,
var=,
grpvarn=,
rowsumyn=,
label=,
append=,
libout,
dtout=
);
替換這一步我就不展示。使用SAS EG
的工具欄-編輯-替換
或者Ctrl + H
進(jìn)行代碼替換
岔擂。
然后包裝進(jìn)宏里位喂,試著運(yùn)行一下。
注意到這一步乱灵,不要最后的4
個(gè)參數(shù)塑崖,是可以運(yùn)行成功的。
小數(shù)點(diǎn)位數(shù)
不同的統(tǒng)計(jì)指標(biāo)要保留的小數(shù)點(diǎn)位數(shù)是不一樣的痛倚,更和原始數(shù)據(jù)的位數(shù)有關(guān)规婆。
我不知道不同公司是否要求有所不同,我依據(jù)我們公司的原則蝉稳,限定如下:
-
n
和nmissing
都是整數(shù)部分抒蚜;
min
和max
指標(biāo)保留位數(shù),和原始數(shù)據(jù)最大小數(shù)位數(shù)一致
耘戚;- 當(dāng)原始數(shù)據(jù)最大小數(shù)位數(shù)
(decmax)
小于等于2
時(shí):mean嗡髓、median、q1
和q3
保留decmax + 1
位毕莱;std
保留decmax + 2
位器贩;- 當(dāng)原始數(shù)據(jù)最大小數(shù)位數(shù)
(decmax)
等于3
時(shí):mean颅夺、median、q1
和q3
保留decmax + 1
位蛹稍;std
保留4
位吧黄;- 當(dāng)原始數(shù)據(jù)最大小數(shù)位數(shù)
(decmax)
大于3
時(shí):mean、median唆姐、q1拗慨、q3
和std
均保留4
位;
好的奉芦,根據(jù)這些原則赵抢,下面利用代碼實(shí)現(xiàn)。
- 待分析變量的小數(shù)位數(shù)宏變量
data _stdt0;
set &libin..&dtin.;
run;
data _adsl;
set &adsl.;
run;
* _1. pre-processing;
* _1.1 decimals ;
data _dec;
set _stdt0;
dec = length(scan(strip(put(&var., best.)),2,"."));
if not index(&var.,".") then dec = 0;
run;
proc sql ;
select max(dec) into: decmax
from _dec
;
quit;
%put 最大小數(shù)位數(shù):&decmax.;
通過上面的代碼声功,將待分析變量的最大小數(shù)位數(shù)賦值給宏變量decmax
烦却。
- 拼接步驟代碼的修改
這樣子,上述拼接步驟的代碼就可以按照小數(shù)點(diǎn)保留的原則
進(jìn)行修改了先巴,修改后的代碼如下:
* _3.2 Variable construction of the target format;
data _combdt;
length _1nnmiss _2meansd _3median _4q1q3 _5minmax $200.;
set _dt4comb;
_1nnmiss =cats( strip(put(n ,8.0)) , "(",strip(put(count - n , 8.0)), ")");
_5minmax = cats( strip(put( round(min , 10**-( &decmax.) ) , 8.%eval( &decmax.)) ) , "~" ,strip(put( round(max , 10**-( &decmax.) ) , 8.%eval( &decmax.)) ) );
%if &decmax. <= 2 %then %do;
_2meansd = cats( strip(put( round(mean , 10**-( &decmax. + 1) ), 8.%eval( &decmax. + 1) ) ) , "(" ,strip(put( round(std, 10**-( &decmax. + 2)), 8.%eval( &decmax. + 2)) ) , ")");
_3median = cats( strip(put( round(mid , 10**-( &decmax. + 1) ) , 8.%eval( &decmax. + 1) ) ) );
_4q1q3 = cats( strip(put( round(q1 , 10**-( &decmax. + 1) ) , 8.%eval( &decmax. + 1) ) ) , "~" ,strip(put( round(q3 , 10**-( &decmax. + 1) ) , 8.%eval( &decmax. + 1) ) ) );
%end;
%if &decmax. = 3 %then %do;
_2meansd = cats( strip(put( round(mean , 10**-( &decmax. + 1) ), 8.%eval( &decmax. + 1) ) ) , "(" ,strip(put( round(std, 0.0001), 8.4) ) , ")");
_3median = cats( strip(put( round(mid , 10**-( &decmax. + 1) ) , 8.%eval( &decmax. + 1) ) ) );
_4q1q3 = cats( strip(put( round(q1 , 10**-( &decmax. + 1) ) , 8.%eval( &decmax. + 1) ) ) , "~" ,strip(put( round(q3 , 10**-( &decmax. + 1) ) , 8.%eval( &decmax. + 1) ) ) );
%end;
%if &decmax. >3 %then %do;
_2meansd = cats( strip(put( round(mean , 0.0001 ), 8.4 ) ) , "(" ,strip(put( round(std, 0.0001), 8.4) ) , ")");
_3median = cats( strip(put( round(mid , 0.0001 ) , 8.4 ) ) );
_4q1q3 = cats( strip(put( round(q1 ,0.0001 ) , 8.4 ) ) , "~" ,strip(put( round(q3 , 0.0001 ) , 8.4 ) ) );
%end;
keep &grpvarn. _1nnmiss _2meansd _3median _4q1q3 _5minmax;
proc sort; by &grpvarn.;
run;
列名的修改
*_3.4 rename column;
proc contents data=_trans2 out=_info noprint;
proc sort;
by varnum;
run;
proc sql noprint;
select count(distinct NAME) , NAME into: varn, :vnam1 -:vnam99 from _info;
quit;
data _&dtout.;
set _trans2;
%do ii = 1 %to &varn.;
%let jj = %eval(&ii. - 1);
rename &&vnam&ii. = C&jj.;
%end;
run;
label
和第一列
的修改
在目標(biāo)表格的第一行是我們統(tǒng)計(jì)的指標(biāo)的名稱其爵,添加代碼如下:
* _3.5 label ;
data _row1;
length C0 $200.;
C0 = cats("&label.");
run;
data _&dtout._;
set _row1
_&dtout.;
if c0 = "_1nnmiss" then C0 = "n(nmisssing)";
if c0 = "_2meansd" then C0 = "Mean(SD)";
if c0 = "_3median" then C0 = "Median";
if c0 = "_4q1q3" then C0 = "Q1~Q3";
if c0 = "_5minmax" then C0 = "Min~Max";
run;
append
有時(shí)候要統(tǒng)計(jì)的變量不止一個(gè),而我們又想下一個(gè)跟在上一個(gè)之后伸蚯,因此設(shè)置了一個(gè)append
參數(shù)
* _3.6 append ;
%if %sysfunc(upcase(&append.)) = %str(Y) and %sysfunc(exist(&dtout., data) ) %then %do;
data &dtout.;
set %if %sysfunc(exist(&dtout., data) ) %then &dtout.; _&dtout._ ;
run;
%end;
%else %do;
%put WARNING: 未追加數(shù)據(jù)集;
data &dtout.;
set _&dtout._ ;
run;
%end;
數(shù)據(jù)集輸出和清除臨時(shí)數(shù)據(jù)集
* _4 output data ;
* _4.1 output ;
data &libout..&dtout.;
set &dtout.;
run;
* _4.2 remove temp datasets ;
proc datasets lib=work;
delete _:;
run;
總結(jié)
以上就是我寫這個(gè)宏的最主要代碼摩渺,還有一些小判斷就不展示了。
完整代碼如下:
%macro MeanT(
libin=,
dtin=,
adsl=,
var=,
grpvarn=,
rowsumyn=,
label =,
append=,
libout=,
dtout=
);
data _stdt0;
set &libin..&dtin.;
run;
data _adsl;
set &adsl.;
run;
* _1. pre-processing;
* _1.1 decimals ;
data _dec;
set _stdt0;
dec = length(scan(strip(put(&var., best.)),2,"."));
if not index(&var.,".") then dec = 0;
run;
proc sql ;
select max(dec) into: decmax
from _dec
;
quit;
%put 最大小數(shù)位數(shù):&decmax.;
* _1.2.1 for sum column ;
data _adsum;
set _stdt0;
&grpvarn. = 999;
arm = "合計(jì)";
run;
data _adslall;
set _adsl;
&grpvarn. = 999;
arm = "合計(jì)";
run;
* _2.main statistical steps; ;
* _2.1 Calculation of target variable statistics;
* _2.1.1.1 by group;
proc means data=_stdt0 noprint ;
var &var.;
by &grpvarn. ;
output out=_bygrpm0 N= n nmiss=nmiss mean=mean STD=std median = mid q1=q1 q3= q3 max=max min=min;
run;
* _2.1.1.2 Calculation of number of every group;
proc freq data=_adsl noprint;
table &grpvarn. / out=_bygrpnum;
proc sort ; by &grpvarn.;
run;
* _2.1.1.3 combine ;
proc sort data=_bygrpm0; by &grpvarn.;run;
data _bygrp;
merge _bygrpm0
_bygrpnum(drop = percent);
by &grpvarn.;
run;
* _2.main statistical steps; ;
* _2.2 Calculation of sum column statistics;
* _2.2.1 Calculation of sum column of target variable statistics;
proc means data=_adsum noprint ;
var &var.;
by &grpvarn.;
output out=_summ0(drop=_TYPE_) N= n nmiss=nmiss mean=mean STD=std median = mid q1=q1 q3= q3 max=max min=min;
run;
* _2.2.2 Calculation of number of all subject;
proc freq data=_adslall noprint;
table &grpvarn. / out=_sumnum;
proc sort ; by &grpvarn.;
run;
* _2.2.3 combine ;
proc sort data=_summ0; by &grpvarn.;run;
data _sum;
merge _summ0
_sumnum(drop = percent);
by &grpvarn.;
run;
* _3 processing step of stat;
* _3.1 processing step of stat;
%if %sysfunc(upcase(&rowsumyn.)) = %str(Y) %then %do;
%put WARNING: 將計(jì)算合計(jì)列;
data _dt4comb;
set _bygrp
_sum;
run;
%end;
%else %do;
%put WARNING: 不計(jì)算合計(jì)列;
data _dt4comb;
set _bygrp;
run;
%end;
* _3.2 Variable construction of the target format;
data _combdt;
length _1nnmiss _2meansd _3median _4q1q3 _5minmax $200.;
set _dt4comb;
_1nnmiss =cats( strip(put(n ,8.0)) , "(",strip(put(count - n , 8.0)), ")");
_5minmax = cats( strip(put( round(min , 10**-( &decmax.) ) , 8.%eval( &decmax.)) ) , "~" ,strip(put( round(max , 10**-( &decmax.) ) , 8.%eval( &decmax.)) ) );
%if &decmax. <= 2 %then %do;
_2meansd = cats( strip(put( round(mean , 10**-( &decmax. + 1) ), 8.%eval( &decmax. + 1) ) ) , "(" ,strip(put( round(std, 10**-( &decmax. + 2)), 8.%eval( &decmax. + 2)) ) , ")");
_3median = cats( strip(put( round(mid , 10**-( &decmax. + 1) ) , 8.%eval( &decmax. + 1) ) ) );
_4q1q3 = cats( strip(put( round(q1 , 10**-( &decmax. + 1) ) , 8.%eval( &decmax. + 1) ) ) , "~" ,strip(put( round(q3 , 10**-( &decmax. + 1) ) , 8.%eval( &decmax. + 1) ) ) );
%end;
%if &decmax. = 3 %then %do;
_2meansd = cats( strip(put( round(mean , 10**-( &decmax. + 1) ), 8.%eval( &decmax. + 1) ) ) , "(" ,strip(put( round(std, 0.0001), 8.4) ) , ")");
_3median = cats( strip(put( round(mid , 10**-( &decmax. + 1) ) , 8.%eval( &decmax. + 1) ) ) );
_4q1q3 = cats( strip(put( round(q1 , 10**-( &decmax. + 1) ) , 8.%eval( &decmax. + 1) ) ) , "~" ,strip(put( round(q3 , 10**-( &decmax. + 1) ) , 8.%eval( &decmax. + 1) ) ) );
%end;
%if &decmax. >3 %then %do;
_2meansd = cats( strip(put( round(mean , 0.0001 ), 8.4 ) ) , "(" ,strip(put( round(std, 0.0001), 8.4) ) , ")");
_3median = cats( strip(put( round(mid , 0.0001 ) , 8.4 ) ) );
_4q1q3 = cats( strip(put( round(q1 ,0.0001 ) , 8.4 ) ) , "~" ,strip(put( round(q3 , 0.0001 ) , 8.4 ) ) );
%end;
keep &grpvarn. _1nnmiss _2meansd _3median _4q1q3 _5minmax;
proc sort; by &grpvarn.;
run;
* _3.3 transpose;
proc transpose data=_combdt out=_trans1;
var _1nnmiss _2meansd _3median _4q1q3 _5minmax;
by &grpvarn.;
proc sort; by _NAME_ ;
run;
proc transpose data=_trans1 out=_trans2 prefix= _grp;
id &grpvarn.;
var col1;
by _NAME_ ;
run;
*_3.4 rename column;
proc contents data=_trans2 out=_info noprint;
proc sort;
by varnum;
run;
proc sql noprint;
select count(distinct NAME) , NAME into: varn, :vnam1 -:vnam99 from _info;
quit;
data _&dtout.;
set _trans2;
%do ii = 1 %to &varn.;
%let jj = %eval(&ii. - 1);
rename &&vnam&ii. = C&jj.;
%end;
run;
* _3.5 label ;
data _row1;
length C0 $200.;
C0 = cats("&label.");
run;
data _&dtout._;
set _row1
_&dtout.;
if c0 = "_1nnmiss" then C0 = "n(nmisssing)";
if c0 = "_2meansd" then C0 = "Mean(SD)";
if c0 = "_3median" then C0 = "Median";
if c0 = "_4q1q3" then C0 = "Q1~Q3";
if c0 = "_5minmax" then C0 = "Min~Max";
run;
* _3.6 append ;
%if %sysfunc(upcase(&append.)) = %str(Y) and %sysfunc(exist(&dtout., data) ) %then %do;
data &dtout.;
set %if %sysfunc(exist(&dtout., data) ) %then &dtout.; _&dtout._ ;
run;
%end;
%else %do;
%put WARNING: 未追加數(shù)據(jù)集;
data &dtout.;
set _&dtout._ ;
run;
%end;
* _4 output data ;
* _4.1 output ;
data &libout..&dtout.;
set &dtout.;
run;
* _4.2 remove temp datasets ;
proc datasets lib=work;
delete _:;
run;
%mend;