SAS給宏變量賦值大體來(lái)說(shuō)其實(shí)就3種方式:%let語(yǔ)句、data步中的call symput語(yǔ)句和proc sql過(guò)程中into語(yǔ)句。
這里根據(jù)變量和觀(guān)測(cè)的數(shù)量分情況進(jìn)行如下討論,即:
- 單變量單觀(guān)測(cè)變單宏變量
- 單變量單觀(guān)測(cè)變多宏變量
- 單變量多觀(guān)測(cè)變多宏變量
單變量單觀(guān)測(cè)變單宏變量
提出問(wèn)題如下:
/*problem1:將組名信息賦值給宏變量group,各組之間\分割,單變量一觀(guān)測(cè)變一宏變量*/
數(shù)據(jù)集如下:
data example1;
group = "太極組\圍棋組\古箏組\書(shū)法組";
run;

分別使用如下3種方法進(jìn)行宏變量賦值:
/*method1: let statement*/
%let group1 = 太極組\圍棋組\古箏組\書(shū)法組;
%put &group1.;

/*method2:data步 call symput statement*/
data _null_;
set example1;
call symput("group2",group);
run;
%put &group2.;
日志信息

/*method3:proc sql statement*/
proc sql;
select group into: group3
from example1
;
quit;
%put &group3.;

- 說(shuō)明
proc sql;
/* create table macros as*/
select *
from dictionary.macros
;
quit;
上述語(yǔ)句是獲得環(huán)境中macros變量信息的語(yǔ)句,很實(shí)用。
在單變量賦值單宏變量時(shí),%let語(yǔ)句相比其他兩種要簡(jiǎn)單,不必基于數(shù)據(jù)集;而proc sql語(yǔ)句則必須基于數(shù)據(jù)集中的變量產(chǎn)生;call symput則均可以實(shí)現(xiàn)。
單變量單觀(guān)測(cè)變多宏變量
- 問(wèn)題
/*problem2:將組名信息分別依次賦值給宏變量term1,term2,...,單變量一觀(guān)測(cè)變多宏變量*/
- 數(shù)據(jù)集如下:
data example2;
group = "太極組\圍棋組\古箏組\書(shū)法組";
run;

分別使用如下3種方法進(jìn)行宏變量賦值:
/*method1: let statement*/
%let term1_1 = 太極組;
%let term1_2 = 圍棋組;
%let term1_3 = 古箏組;
%let term1_4 = 書(shū)法組;
%macro batch;
%do i = 1 %to 4;
%let _term1_&i. = %qscan("太極組\圍棋組\古箏組\書(shū)法組" , &i. , "\");
%end;
proc sql;
/* create table macros as*/
select *
from dictionary.macros
where scope = "BATCH"
;
quit;
%mend;
%batch;

/*method2:data步 call symput statement*/
data _null_;
set example2
do i = 1 to 4;
call symput(cats("term2_", put(i , best.)) , scan(group , i, "\") );
end;
run;

/*method3:proc sql statement*/
data m3;
set example2
array term (4) $ term1 - term4;
do i =1 to 4;
term(i) = scan(group , i, "\") ;
end;
run;
proc sql;
select term1, term2, term3, term4 into :term3_1 ,:term3_2 ,:term3_3,:term3_4
from m3
;
quit;
proc sql;
/* create table macros as*/
select *
from dictionary.macros
;
quit;

- 說(shuō)明
- 這種情況就可以看出 %let語(yǔ)句的劣勢(shì)了,無(wú)法批量操作,為了批量操作我寫(xiě)了個(gè)簡(jiǎn)單宏才實(shí)現(xiàn);
- call symput語(yǔ)句的實(shí)現(xiàn)則很簡(jiǎn)單,這是因?yàn)橹簧婕暗絾蝹€(gè)變量的操作,是data步的優(yōu)勢(shì)所在,代碼量很少;
- 而proc sql給宏變量賦值的優(yōu)勢(shì)在這里體現(xiàn)的不明顯,但是也可以看出它針對(duì)數(shù)據(jù)集層面,批量化宏變量賦值操作的便捷性。
單變量多觀(guān)測(cè)變多宏變量
- 問(wèn)題
/*problem3:將分組變量中組名觀(guān)測(cè)依次賦值給宏變量term1,term2,...,單變量多觀(guān)測(cè)變多宏變量*/
- 數(shù)據(jù)集
data example3;
length group $200.;
input group;
cards;
太極組
圍棋組
古箏組
書(shū)法組
;
proc print;
run;
example3打印結(jié)果

- 使用3種方法賦值宏變量
/*method1:%let statement*/
proc transpose data= example3 out=_out3;
var group;
run;
%macro m1;
data test;
set _out3;
call symput("group" ,catx("\", of col1 - col4) );
run;
%do i = 1 %to 4;
%let _1term_&i. = %qscan( "&group.", &i.,"\");
%end;
proc sql;
create table macros as
select *
from dictionary.macros
where scope = "M1"
;
quit;
%mend;
%m1;


使用%let解決這個(gè)問(wèn)題,需要先轉(zhuǎn)置,使問(wèn)題變?yōu)榛谧兞浚簿褪橇?,彌補(bǔ)基礎(chǔ)語(yǔ)句基于觀(guān)測(cè)處理問(wèn)題能力偏弱的短板;
然后構(gòu)建宏,在宏里還要再把數(shù)據(jù)集里的多個(gè)變量賦值為單個(gè)宏變量,這是因?yàn)?strong>%let是在變量層面解決問(wèn)題的,數(shù)據(jù)集無(wú)處下爪;
之后使用循環(huán),彌補(bǔ)%let批量處理問(wèn)題的短板。
/*method2:call symput statement*/
proc transpose data= example3 out=_out3;
var group;
run;
data M2;
set _out3;
array terms(4) col1 -col4;
do i = 1 to 4;
call symput(cats("_2term_", put(i , best.)),terms(i) );
end;
run;
proc sql;
select *
from dictionary.macros
;
quit;

- 說(shuō)明
可以看到,使用call symput解決這個(gè)問(wèn)題,同樣需要經(jīng)歷轉(zhuǎn)置步驟轉(zhuǎn)變?yōu)樘幚碜兞康膯?wèn)題;然后在data步使用數(shù)組循環(huán),還是比較繁瑣的。
- 而proc sql的優(yōu)勢(shì)就體現(xiàn)出來(lái)了,一個(gè)代碼塊就達(dá)成目的,如下:
/*method3:proc sql statement*/
/*單變量多觀(guān)測(cè)變多個(gè)宏變量*/
proc sql;
select group into :_3term1 -: _3term99
from example3
;
quit;
/*單變量多觀(guān)測(cè)變一宏變量*/
proc sql;
select group into :_3term separated by " "
from example3
;
quit;
proc sql;
/* create table macros as*/
select *
from dictionary.macros
;
quit;

- 說(shuō)明
- 這種情況%let的實(shí)現(xiàn)一樣要借助于宏,并且因?yàn)樯婕暗搅藬?shù)據(jù)集層面的操作,%let就更加不太擅長(zhǎng)了;
- 同時(shí),call symput的實(shí)現(xiàn)也不太容易,SAS data步長(zhǎng)于變量操作弱于觀(guān)測(cè)操作的弊端便體現(xiàn)出來(lái)了。
- 在這種情況下,proc sql的批量化和觀(guān)測(cè)層面操作的優(yōu)勢(shì)便體現(xiàn)出來(lái)了,如果是有多變量多觀(guān)測(cè)賦值多宏變量的情況,那proc sql的優(yōu)勢(shì)就會(huì)更加明顯了;
proc sql給宏變量賦值的情況大致可以分為如下幾種情況
-
單變量單個(gè)觀(guān)測(cè)值賦值給單個(gè)宏變量:
proc sql; select var into :mvar from dtin ; quit;,這種情況用proc sql不具有優(yōu)勢(shì);
-
多變量單觀(guān)測(cè)值賦值給多個(gè)宏變量:
proc sql; select var1, var2, var3, var4 into :mvar1, mvar2, mvar3, mvar4 from dtin ; quit;
-
單變量多觀(guān)測(cè)賦值給多個(gè)宏變量:
proc sql; select var1into :mvar1 -:mvar99 from dtin ; quit;,其中,mvar99中的數(shù)值設(shè)置的較大值,是在未知觀(guān)測(cè)值數(shù)量時(shí)的簡(jiǎn)便做法;
-
單變量多觀(guān)測(cè)賦值給單個(gè)宏變量:
proc sql; select var1into :mvar separated by "sep" from dtin ; quit;,其中,sep是分隔符;
-
多變量多觀(guān)測(cè)值賦值給多個(gè)宏變量:
proc sql; select var1, var2, var3, var4 into :var1m1 -:var1m99, var2m1 -:var2m99, var3m1 -:var3m99, var4m1 -:var4m99 from dtin ; quit;,其中的4個(gè)變量均有多個(gè)觀(guān)測(cè)值;
- 舉例
proc sql;
select name, weight, height into :name1 -:name99,
:weight1 -:weight99,
:height1 -: height99
from sashelp.class(where = (sex = "女"))
;
quit;

-
多變量多觀(guān)測(cè)值賦值給多個(gè)宏變量,但變量?jī)?nèi)觀(guān)測(cè)值拼接:
proc sql; select var1, var2, var3, var4 into :var1m1 -:var1m99, var2m1 -:var2m99, var3m1 -:var3m99, var4m1 -:var4m99 from dtin ; quit;,其中的4個(gè)變量均有多個(gè)觀(guān)測(cè)值;
proc sql;
select name, weight, height into :name separated by " ", :weight separated by " " ,:height separated by " "
from sashelp.class(where = (sex = "女"))
;
quit;

總結(jié)
不涉及數(shù)據(jù)集的單變量的宏變量賦值,%let很實(shí)用;
基于數(shù)據(jù)集且多在變量層面操作,call symput和proc sql均適用;
基于數(shù)據(jù)集且涉及多個(gè)變量和觀(guān)測(cè)層面的操作,proc sql比較有優(yōu)勢(shì),其他兩種實(shí)現(xiàn)起來(lái)就需要更多的代碼量;