歡迎關(guān)注,SAS茶談!
前面文章SAS編程-小知識:import過程步的Guessingrows選項介紹了導(dǎo)入txt文本的遇到的問題,由于“NA”字符的存在,之前一些本是數(shù)值型的變量導(dǎo)入SAS數(shù)據(jù)集后,變成了字符型變量。
為方便后續(xù)的編程,需要將其轉(zhuǎn)化為字符變量,“NA”的記錄直接賦值為空值。這個在RawData處理中,還是比較常見的。
對于單個變量處理如下:
data test;
set test0(rename=(var1 = var1_));
if var1_ ne "NA" then var1 = input(strip(var1_), best.);
else var1 = .;
run;
如果需要轉(zhuǎn)化的變量較少,依次手動寫程序是沒什么問題的。可一旦變量數(shù)目上去,依次硬寫無疑是一件低效的事情。這時候,考慮利用宏變量批量構(gòu)建SAS語句進行實現(xiàn)。
這篇文章介紹利用宏變量批量構(gòu)建SAS語句,內(nèi)容涉及將一列變量所有值保存到宏變量中。
1. 實現(xiàn)思路
批量構(gòu)建的第一步是,明確完成狀態(tài)下的程序是怎么樣的。不同的實現(xiàn)路徑,批量構(gòu)建的內(nèi)容也不同。
以上面單變量處理為例,rename語句的實現(xiàn)比較單一,直接增加變量賦值等式就好。而if語句的處理就可以有多種,例如,有多少個變量,就對應(yīng)有多少個if語句;例如,通過宏循環(huán)進行處理;例如,通過數(shù)組循環(huán)進行處理。
這里以數(shù)組循環(huán)舉例,演示數(shù)據(jù)集為SASHelp.Class。目標(biāo)是每個數(shù)值型變量+2并轉(zhuǎn)化為字符型變量,并且變量的名稱不變。

根據(jù)目標(biāo),思考下程序的大體邏輯:
- 為避免變量屬性沖突,需要對原變量名稱Rename;
- 新建數(shù)組需要獲取原數(shù)值變量名稱,以及對應(yīng)的Rename語句;
- 數(shù)組循環(huán)需要考慮到數(shù)值變量的數(shù)目。
2. 變量信息的獲取
獲取數(shù)據(jù)集的數(shù)值變量名稱,方便后續(xù)構(gòu)建對應(yīng)的SAS語句:
data column;
set sashelp.vcolumn; *;
where libname = "SASHELP" and memname = "CLASS" and type = "num";
length name_r rename $50;
name_r = strip(name)||"_";
rename = strip(name) || " = " || strip(name_r);
keep name: rename ;
run;
輸出結(jié)果如下:

3. 利用宏變量構(gòu)建SAS語句
最后實現(xiàn)的目標(biāo)程序如下:
data class;
set sashelp.class(rename=(Age = Age_ Height = Height_ Weight = Weight_));
array num{3} Age_ Height_ Weight_;
array char{3} $ 8 Age Height Weight;
do i = 1 to 3;
char{i} = strip(put(num{i} + 2, best.));
end;
drop Age_ Height_ Weight_ i;
run;
結(jié)合數(shù)據(jù)集以及目標(biāo)程序,我們需要將列內(nèi)容拼接并保存到宏變量中。生成宏變量可以使用Data步和Proc SQL,下面分別以這兩種方法進行實現(xiàn)。
3.1 Data步生成宏變量
在Data步中,可以使用symputx將變量值賦值到宏變量。而整理內(nèi)容的拼接整合,可以通過Retain變量進行實現(xiàn)。內(nèi)容拼接完畢后,在數(shù)據(jù)的最后一行,將值賦值給宏變量。
data tmp;
set column end=eof;
length name_m name_r_m rename_m $1000;
retain name_m name_r_m rename_m " ";
name_m = strip(name_m )||" "||strip(name);
name_r_m = strip(name_r_m )||" "||strip(name_r);
rename_m = strip(rename_m )||" "||strip(rename);
if eof then do;
call symputx("var_char", strip(name_m) );
call symputx("var_num", strip(name_r_m) );
call symputx("var_rename", strip(rename_m ) );
call symputx("n", strip(put(_n_, best.)) );
end;
run;
%put var_char = &var_char.;
%put var_num= &var_num.;
%put var_rename= &var_rename.;
%put n= &n.;
數(shù)據(jù)集輸出如下:

宏變量輸出如下:

宏變量設(shè)置完畢后,目標(biāo)程序中的特定SAS語句就可以使用宏變量替代。
data class;
set sashelp.class(rename=(&var_rename.));
array num{&n.} &var_num.;
array char{&n.} $ 8 &var_char.;
do i = 1 to &n.;
char{i} = strip(put(num{i} + 2, best.));
end;
drop &var_num. i;
run;
運行之后,最后的數(shù)據(jù)集處理如下:

這樣處理既實現(xiàn)了既定的效果,同時,也避免了依次單獨處理每個變量。在大批量的變量處理中,這是非常高效的。
3.2 SQL過程步生成宏變量
SQL過程步通過into :子句生成宏變量,具體方法在SAS編程:Proc SQL生成宏變量時INTO子句的使用 中有過介紹,我們需要使用第3種形式:
- into : macro-variable(指定一個或多個宏變量)
- into : macro-variable-1 ? : macro-variable-n <NOTRIM> (指定一個宏變量序列)
- into : macro-variable SEPARATED BY 'characters ' <NOTRIM> (指定一個宏變量來保存一列的所有值)
具體程序如下:
proc sql noprint;
select name into: var_char separated by " " from column;
select name_r into: var_num separated by " " from column;
select rename into: var_rename separated by " " from column;
select count(*) into: n from column;
quit;
%put var_char = &var_char.;
%put var_num= &var_num.;
%put var_rename= &var_rename.;
%put n= &n.;
宏變量輸出結(jié)果如下:

與Data步相比,SQL過程步顯得更簡潔,不需要對行記錄進行拼接處理。后續(xù),調(diào)用的宏變量的代碼同Data步,這里不再演示。
總結(jié)
編程中遇到大量同類型的處理需求時,需要考慮批量處理。批量處理的方式有很多,本篇文章使用的方法是將需要的程序元素保存到宏變量中。
生成宏變量可以通過Data步中的call symputx語句,也可以通過SQL中的into :子句。本篇需要將一列變量的所有值保存到宏變量中,通過Data步實現(xiàn)要利用retain語句進行拼接。
感謝閱讀, 歡迎關(guān)注:SAS茶談!
若有疑問,歡迎評論交流!