前幾天朋友又問了一個問題,朋友手上資料有一串數字,例如5、6、20等,希望能在數字前面補零,補成為005、006、020。因為他的資料很多,而且數字長度不一定,從1~9999都有可能,因此沒辦法用CAT系列函數將零組合到數字前面。
由這個問題,開始這篇第一個程式,建立範例資料(這是我的習慣,沒有資料我寫不出程式>"< )
data zero1_1;
input num1;
datalines;
1
25
562
9480
X
;
proc print data=zero1_1;
run;
接下來不囉唆,直接使用Format就可以解決這個問題了,而這裡要使用的Format為Zw.d
data zero1_2;
set zero1_1;
format num1 z5.;
run;
proc print data=zero1_2;
run;
結果為下圖
只要簡簡單單使用Z5.這個格式便可以處理了。Z後面接這個5是指數字的總長度,因此以第4個觀察值來說,原本的數字就有4位了,因此SAS會只補一個0了。
其實朋友的問題比上述的狀況困難了一點,資料中欲轉換的變項為文字格式,他也希望在補零後依然保持文字格式…好吧這真的比較討厭了。依據朋友的說法在建另一個資料吧(同樣沒有資料我不會寫程式>"< )
data zero2_1;
input num1 $;
datalines;
1
25
562
9480
X
5X6
;
proc print data=zero2_1;
run;
下一段程式就可以完成朋友的需求了,不過大家有無注意到,資料中有幾個討厭的東西,也就是「X」和「5X6」這兩個純文字的訊息,朋友希望能完整保留到新的變項中,因此程式寫法調整為
data zero2_2;
set zero2_1;
num2=put(input(num1, best5.), z5.);
if missing(input(num1, best5.)) then num2=num1;
run;
proc print data=zero2_2;
run;
以上這隻程式主要就是利用INPUT(文字轉數字),和PUT(數字轉文字)這兩個函數組合實用,及達到朋友的需求了(可以要求請客了 YA~)。而if missing..這一行語法是用來判斷num1中有沒有不能轉成數字的,如果不能轉,就直接取代num2中的值
其實INPUT和PUT的功能很強大,大家可以去GOOGLE看看。就SAS HELP這兩個函數的說明及語法為:
INPUT Function
Returns the value that is produced when SAS converts an expression using the specified informat.
INPUT(source, <? | ??>informat.)
PUT Function
Returns a value using a specified format.
PUT(source, format.)
結果如下圖:
接下來我就想到,要如何把這個概念應用到Macro中了。在實際經驗中,許多政府機關提供的資料,常以補零數字作為資料的檔案名稱,例如CD201201、CD201205、CD201212等,如果要寫Macro的迴圈早期我都會用%if %then的方法寫,現在回想起來還真的是很天真可愛無邪...
一樣我們來建立一組類似的資料(10個資料)
data M001 M002 M003 M004 M005 M006 M007 M008 M009 M010 M011 M012 ;
set zero2_1;
run;
假如我只想單純將資料都列印出來,但先來一個『錯誤』的寫法,讓大家欣賞一下~
%macro print_loop1 (start, end);
%do i=&start %to &end;
proc print data=m&i;
run;
%end;
%mend print_loop1;
%print_loop1 (001,012);
在LOG中可以看到一下錯誤訊息
而正確的寫法應該為%print_loop2的寫法
%macro print_loop2 (start, end);
%do i=&start %to &end;
%let II=%sysfunc( PUTN(&i,z3.) );
proc print data=m&II;
run;
%end;
%mend print_loop2;
%print_loop2 (001,012);
這裡的重點語法為
%let II=%sysfunc( PUTN(&i,z3.) );
%sysfunc為Macro很重要的函數,因為SAS內建的Macro Function不多,但透過%sysfunc這個巨集函數便可使用SAS內建函數(大部分),但大家一定很好奇,為何函數改成PUTN了,因為……因為…… 就「PUT」那麼剛好不能被%sysfunc使用!!
再寫一段複雜一點的Macro,此Macro的目的在把每一個資料檔加入補過零編號,然後堆疊在一起,程式的細節我就不贅述了。
%macro append_loop1 (start, end);
%do i=&start %to &end;
%let II=%sysfunc( PUTN(&i,z3.) );
/*在資料中增加編號*/
data m&II._new;
format index $3.;
set m&II;
index="&II";
run;
/*將所有資料堆疊起來*/
proc append
base=total
data=m&II._new;
run;
%end;
%mend append_loop1;
%append_loop1 (001,012);
沒有留言:
張貼留言