在 SAS 資料處理的過程中,使用者會發現,當複製一個變數並給予新的變數名稱時,舊變數的格式雖然會一併複製到新變數裡面,但舊變數的 label 卻沒有辦法複製過去。若只有一兩個變數時還可以用手動的方式在 data step 裡面重打,但若變數過多時,這就會成為一個相當棘手的問題。John Ladds 提供了一個簡易的方式來解決這個 label 複製的問題。
以下面這個資料集當作範例:
proc format;
value OriginalOrderAgree
1 = 'Strongly agree'
2 = 'Somewhat agree'
3 = 'Neither agree nor disagree'
4 = 'Somewhat disagree'
5 = 'Strongly disagree'
6 = 'Not applicable'
97 = "Don't know"
99 = 'Not stated';
value ReverseOrderAgree
5 = 'Strongly agree'
4 = 'Somewhat agree'
3 = 'Neither agree nor disagree'
2 = 'Somewhat disagree'
1 = 'Strongly disagree'
other='Missing';
run;
** Create some test data;
data work.theData;
input @01 id $10.
@11 Q001 2.
@13 Q002 2.
@15 Q003 2.
@17 Q004 2.
@19 Q005 2.
@21 Q006 2.
@23 Q007 2.
@25 Q008 2.
@27 Q009 2.
@29 Q010 2.;
label Q001 = "Have material's and equipment I need";
label Q002 = "Material and tools avail in lang choice";
label Q003 = "I use the language of my choice";
label Q004 = "My jobs fits my interests.";
label Q005 = "I have support at work.";
label Q006 = "I am satisfied, current work arrangement";
label Q007 = "I can claim overtime";
label Q008 = "Overall, I like my job.";
label Q009 = "I get satisfaction from my work.";
label Q010 = "I know how my work contributes";
format Q001-Q010 OriginalOrderAgree.;
datalines4;
1234567890 1 2 3 4 5 6 1 2 3 4;
1234567892 2 3 4 5 1 1 2 3 4 5;
1234567893 3 4 5 1 2 2 2 3 5 1;
1234567894 4 5 1 2 3 3 3 3 1 2;
1234567895 5 1 2 3 4 4 4 4 2 3;
1234567896 1 2 3 4 5 5 5 5 3 4;
1234567897 2 3 4 5 1 1 1 1 4 5;
1234567898 3 4 5 1 2 2 2 2 5 1;
1234567899 4 598 2 3 3 3 3 1 2;
123456781099 199 3 4 4 4 5 2 3;
;;;;
run;
根據這個資料集,裡面有十個變數,從Q001~Q010,每個變數為數據「1,2,3,4,5」。現在假設要製造新變數R_Q001~R_Q010,而這些新變數是將就舊變數的數據倒轉過來,也就是 1 變成 5,2 變成 4,...,5 變成 1。於是作者利用下面這個 macro 來處理這段:
%macro reverseValueOrder(Q=,Qfmt=);
select(&Q.);
when(1) R_&Q.=5;
when(2) R_&Q.=4;
when(3) R_&Q.=3;
when(4) R_&Q.=2;
when(5) R_&Q.=1;
otherwise R_&Q.=.;
end;
** Transfer the questions label to the new variable;
if eof then call execute("label R_&Q.="||'"'||strip(vlabel(&Q.))||'";');
** Add the new value labels to the new variable;
format R_&Q. &Qfmt..;
%mend reverseValueOrder;
其中,「select(&Q);.....end;」主要就是在做變數倒轉的工作,而下面有一行「if...then...」搭配「call execute」便是在處理 label 複製的動作。裡面的 vlabel 函數的作用是將舊變數裡面的 label 給列出來,放在 strip 函式後面主要是移除不必要的空格,並確保 vlabel 函式叫出來的 label 是字串形式。
接著就可以在新的 data step 裡面一邊進行數據倒轉的工作,一邊進行搬移 label 的工作,如下所示:
data work.thedata;
set work.theData end=eof;
** Open the post DATA STEP Processing;
if eof then call execute('data &syslast.; set &syslast.;');
**A. My Job World ;
%reverseValueOrder(Q=Q001, Qfmt=ReverseOrderAgree);
%reverseValueOrder(Q=Q002, Qfmt=ReverseOrderAgree);
%reverseValueOrder(Q=Q003, Qfmt=ReverseOrderAgree);
%reverseValueOrder(Q=Q004, Qfmt=ReverseOrderAgree);
%reverseValueOrder(Q=Q005, Qfmt=ReverseOrderAgree);
%reverseValueOrder(Q=Q006, Qfmt=ReverseOrderAgree);
%reverseValueOrder(Q=Q007, Qfmt=ReverseOrderAgree);
%reverseValueOrder(Q=Q008, Qfmt=ReverseOrderAgree);
%reverseValueOrder(Q=Q009, Qfmt=ReverseOrderAgree);
%reverseValueOrder(Q=Q010, Qfmt=ReverseOrderAgree);
;... ... ... ... ... ... ... ... ... ... ... **
** Close the post DATA STEP Processing;
if eof then call execute ('run;');
run;
特別提醒的地方有三個。一是 set 後面一定要加上「end=eof」字樣。二是執行 macro 前加上「if eof then call execute('data &syslast.; set &syslast.;'); 」,目的是確保程式執行的資料是當前資料。所以記得在運作此程式之前,別去跑其他不相干的資料。三是結束前加上「if eof then call execute ('run;');」,這樣就大功告成了。
CONTACT INFORMATION
Name: John Ladds
Enterprise: Statistics Canada – SDD SAS Technology Centre
Address: 14-R-90 R.H. Coats Building,
100 Tunney’s Pasture Driveway
Ottawa, Ontario, Canada
K1A 0T6
Phone: 613 951-1767
E-mail: John.Ladds@statcan.gc.ca
Web: www.statcan.ca
沒有留言:
張貼留言
要問問題的人請在文章下方的intensedebate欄位留言,請勿使用blogger預設的意見表單。今後用blogger意見表單留言的人我就不回應了。