招聘|優質CRO公司新增崗位推薦,快來看看吧!
(1)讓SAS也能用中文變量名
默認的SAS命名規則是無法使用中文等特殊字符作為SAS名,不過我們可以通過validvarname=any系統選項,突破此限制,不僅如此,我們甚至可以通過validmemname=extend系統選項突破數據集名稱的限制。
options validmemname=extend validvarname=any ;
↑突破命名限制
並不推薦,救急情況下可用. 比如突然接到一個幾百個中文變量名的CSV文件
(2)忽略打開SAS數據集提示格式錯誤
有時候會碰到別人給的SAS數據集,用libname設置好邏輯庫後,卻仍然無法打開,總是提示格式錯誤,此時可用nofmterr選項忽略此類錯誤。
options nofmterr;
(3)一鍵清理SAS的所有結果
當SAS結果窗口結果太多,希望儘快清理乾淨,從一個乾淨清爽的基礎重新開始時,dm命令就可以派上用場了。
↑Results樹形目錄下結果很多
dm odsresults "clear"continue;
直接運行上面的代碼,還給你一個清爽的世界,效果如下。
↑Results樹形目錄下結果一鍵清理
(4)逃離「黑洞」錯誤
運行任何SAS代碼,SAS都沒有任何結果,也沒有錯誤反饋,只是在log裡重複顯示你的代碼。這種情況就是所謂的「黑洞」錯誤,你進入了這樣一個「黑洞」,任何運行的SAS代碼都被他吸入,木有任何反饋!
如果還沒遇到過,看來歷練還不夠。運行下面一段宏代碼,再試試後面其他SAS過程步。
%macrotest;
%put This is a "Balk Hole"test;
%put **** %str(Gu's Wechat) ****;
%mend ;
%test
/*以下代碼不管怎麼運行就是沒反應啊*/
proc print data=sashelp.class;
run;
怎麼破?運行下面代碼,可以跳出來!
');
%mend;
其實,這個示例還是比較簡單的,仔細觀察宏定義,發現問題可能就在於單引號不匹配導致。完整的匹配是這樣的:
%put **** %str(Gu's Wechat) ****; %mend ; '); %mend;
但是,如果在複雜一點的宏,可能就沒那麼容易一眼找到問題所在了,所幸的是,可以用一段萬能代碼,多次運行,直到出現錯誤提示,就可以逃離黑洞!這就是:
*';*";*);*/;%mend; run;
(5)SAS EG/SAS Studio寫代碼
初學者,可能總是記不住函數,記不住選項。沒關係,讓SAS自動給我們提示吧。這時,可以試試在SAS EG或者SAS Studio裡寫代碼。
↑SAS studio
(6) 一鍵格式化別人凌亂的代碼
遇到別人寫的無法直視的SAS代碼,難道要白白忍受嗎?別了,在SAS EG裡藉助ctrl+i一鍵縮進代碼,從此整整齊齊,一鍵治好強迫症患者。
↑整理前
↑整理後
(7)修改屬性 attrib
(8)根據條件刪除記錄 if條件 then delete;
(9)分拆數據集 data mastermissing;merge old new(in=x);by id;if x=0 then output missing;else output master;run;
(10)利用attrib刪去所有label data want;set have;attrib _all_label="";run;
(11)keep保留變量data abc;setad;keep name label;run;(12)drop 刪除變量data abc;set ad;drop name label;run;(13)Missing(),如果變量有缺失值,則返回真。 如data test_miss; set learn.blood;if missing(Gender) then MissGender + 1;
if missing(WBC)then MissWBC + 1;if missing(RBC) thenMissWBC + 1;if Chol lt 200 and not missing(Chol) then Level ='Low ';else if Chol ge 200 then Level = 'High';run;當變量名形如x1-x5,可以調用missing(of x1-x5).此種寫法也可用於諸如sum等函數。
(14)Ranuni.返回0到1的隨機數。若以0作為種子,SAS將以系統時間作為種子產生隨機數。
(15)Lag返回前一個觀測值的函數。 看下面的代碼 data look_back; input Time Temperature; Prev_temp = lag(Temperature); Two_back = lag2(Temperature); datalines; 1 60 2 62 3 65 4 70 ; 得到結果為 Listing of LOOK_BACK Prev_ Obs Time Temperature temp Two_back 1 1 60 . . 2 2 62 60 . 3 3 65 62 60 4 4 70 65 62 lag返回前一個觀測值,lag2將返回往前數兩個的觀測值,不是指兩個觀測值。呵呵。lag的一般作用為計算兩個變量的差值。將上例略微修改一下,計算兩天的溫度差。 data diff; input TimeTemperature; Diff_temp = Temperature – lag(Temperature); datalines; 1 60 262 3 65 4 70 ; 當然更直接的用法是用Diff函數。 data diff; input Time Temperature; Diff_temp = dif(Temperature); datalines; 1 60 2 62 3 65 4 70 ;
(16).Compbl:將字符串中兩個或兩個以上的空格刪除只剩一個空格(即 compress blank)。Compress刪除空格或指定的字符。 假設有一個名為電話號碼的變量,由於其來源的不同,導致格式多樣。 Phone (908)232-4856 210.343.4757 (516) 343 - 9293 9342342345 現在想去掉左右括號,點號和-號。 data phone; length PhoneNumber $ 10; setlearn.phone; PhoneNumber = compress(Phone,' ()-.'); drop Phone; run; compress的參數稱為修飾語(modifier),各個修飾語的意思如下 d 刪除數字 a 刪除大小寫字符 i 忽略大小寫 k 保留字符串 s 刪除空格,制表符等 p 刪除標點符號 例如 函數 作用 返回值 compress(String,,'a')刪除所有字符串 123 compress(String,,'kd')刪除除數字外的其它字符 123 compress(String,'wxyz','i')忽略大小寫刪除wxyz 123 compress("A?B C99",,'pd')刪除標點符號和數字 AB C
(17)、連接字符串。||或者!!將連接兩個字符串為一個字符串,其長度等於兩個字符串長度之和。比方說one=ABC,two=DEF,則one||Two將返回ABCDEF. CAT函數等同於||,除了返回的字符串的長度以外,其預設值是200.Cats函數在連接字符串前去掉字符串前面和後面的空格。Catx類似於 Cats,在去掉前後的空格後,會在連接的兩字符串中間插入分隔符。下述代碼為其例子。 title "Demonstrating the Concatenation Functions"; data _null_; Length Join Name1–Name4 $ 15; First = 'Ron '; Last = 'Cody '; Join = ':' || First || ':'; Name1 = First || Last; Name2 = cat(First,Last); Name3= cats(First,Last); Name4 = catx(' ',First,Last); file print; put Join= / Name1= / Name2= / Name3= / Name4= /; run; 輸出結果 Demonstrating the Concatenation Functions Join=:Ron : Name1=Ron Cody Name2=Ron Cody Name3=RonCody Name4=Ron Cody
(18)、Find函數。其語法形式如下 find(string,find-string, modifiers,starting-position)
(19)、字符串拆分函數Scan.Scan函數提出以空格或標點符號隔開的第n個單詞。不同於trim,trim只是提取字符。【功能】從字符表達式s中搜取給定的n個單詞【類別】 字符函數【語法】1. Scan(s,n) n為正數時,從字符s末尾提取n個字符2. Scan(s,n) n為負數時,從字符s開始提取n個字符3. SCAN (s,n<,list-of-delimiters>)【注意】1. 如果缺失指定的生成變量的長度,系統默認長度為200.2. 如果|n|=0或大於字符s的長度,則該函數返回空格。【例子】data a;arg='ABC.DEF(X=Y)';word=scan(arg,3);put word;run; data b;arg='ABC.DEF(X=Y)';word=scan(arg,-3);put word;run;data c;arg='ABC.DEF(X=Y)';word=scan(arg,-20);put word;run;data d;input Arr $ & 22.;ArrivalGate=scan(Arr,1,' ');DepartureGate = scan(Arr,2,' ');put DepartureGate ArrivalGate arr;cards;Arrival DepartureGates;run;
(20)比較字符串函數Compare
(21)模糊匹配函數Spedis. 例如 data fuzzy; input Name $20.; Value = spedis(Name,'Friedman'); datalines; Friedman Freedman Xriedman Freidman Friedmann Alfred FRIEDMAN ; 返回結果如下 Listing of FUZZY Name Value Friedman 0 Freedman 12 Xriedman 25 Freidman 6 Friedmann 3 Alfred 100 FRIEDMAN 87 當兩個字符串完全匹配時,將返回0.第一個字符匹配錯誤,將比其它字符匹配錯誤所得的處罰分數更大。
(22)字符串替換 函數Translate會替換某個字符,而Transwrd會替換某個單詞。例如 data trans; input Answer : $5.; Answer = translate(Answer,'ABCDE','12345'); datalines; 14325 AB123 51492 ; 得到結果如下 Answer ADCBE ABABC EAD9B Tranwrd經常用於標準化地址等,如以Street替換St.,以Road替換Rd.,等等。
高級輸入技巧
(1)讀入部分數據
確定obs=n作為輸入選項,SAS將會讀入n行數據後停止。指定firstobs=m將從第m行開始讀入數據。兩者結合,能夠讀入任何連續的數據行。
(2)條件讀入數據
假設有一份數據,含兩年的訪問數據,問題在於這兩年的數據並不一致,訪問的問題不一樣。如何分年讀入數據呢。下面是數據標本。
001ABED 2005
002AABCD2006
005AADD 2005
007BBCDE2006
009ABABA2006
010DEEB 2005
讀入數據的代碼
data survey;
infile 'c:"books"learning"survey56.txt' pad;
input @9 Year $4. @;
if Year = '2005' then
input @1 Number
@4 Q1
@5 Q2
@6 Q3
@7 Q4;
else if Year = '2006' then
input @1 Number
@4 Q1
@5 Q2
@6 Q2B
@7 Q3
@8 Q4;
run;
注意其中的@,表示以多行input讀入一行數據。再如
data females;
infile 'c:"books"learning"bank.txt' pad;
input @14 Gender $1. @;
if Gender ne 'F' then delete;
input @1 Subj $3.
@4 DOB mmddyy10.
@15 Balance 7.;
run;
如果是在一行數據裡有多條記錄,也就是說一行並不表示一條記錄。如何讀入呢?
data pairs;
input X Y @@;
datalines;
1 2 3 4 5 7 8 9 11 14 13 18 21 27
30 40
;
此處@@表示一行數據讀入多條記錄 。
SAS的輸出系統
SAS的輸出系統(Output Delivery System),縮寫為ODS.每個SAS過程創建輸出對象(output objects),輸出對象能夠被導出到HTML,RTF,PDF和SAS數據集等目的地。
1.導出到HTML.
打算將print和means的結果導出到HTML,兩條語句搞定。
ods html file='c:"books"learning"sample.html';
title "Listing of TEST_SCORES";
proc print data=learn.test_scores;
title2 "Sample of HTML Output - all defaults";
id ID;
var Name Score1-Score3;
run;
title "Descriptive Statistics";
proc means data=learn.test_scores n mean min max;
var Score1-Score3;
run;
ods html close;
在過程的開始設置ODS HTML FIEL,在結束時ODS HTML CLOSE.以FILENAME指定文件名。
將上述語句中的HTML分別置換為RTF或PDF,就能分別創建rtf或pdf格式文檔了。
2.選擇或排除部分輸出
使用ODS SELECT 或ODS EXCLUDE 選擇或排除所輸出的部分。
假設你想使用proc univariate輸出某個變量的前5個最大值和後5個最小值。如下例
ods select extremeobs;
title "Extreme Values of RBC";
proc Univariate data=learn.blood;
id Subject;
var RBC;
run;
得到輸出如下
Extreme Values of RBC
The UNIVARIATE Procedure
Variable: RBC
Extreme Observations
----Lowest---- ----Highest---
Value Subject Obs Value Subject Obs
1.71 525 525 7.99 565 565
2.33 440 440 8.12 984 984
2.55 113 113 8.26 288 288
2.92 293 293 8.43 726 726
3.13 635 635 8.75 135 135
3.將輸出導出到SAS數據集
一般過程都有OUT=選項。然而使用ODS可以選擇你想要要的任何值。假設你使用t-test,這個統計過程會產生t-值和p-值。然而從PROC TTEST中產生的數據集中並不能得到這兩個值。使用ODS,將t-test的輸出導出到一個結果集。
ods listing close;
ods output ttests=t_test_data;
proc ttest data=learn.blood;
class Gender;
var RBC WBC Chol;
run;
ods listing;
title "Listing of T_TEST_DATA";
proc print data=t_test_data;
run;
註:在過程中不能加入NOPRINT選項。不然,ODS不能得到結果。
導出到數據集後,可以進行更進一步的分析。
提高SAS運行效率的技巧
利用SAS處理一個大數據量的時候,使用一些小技巧可以很好的提高SAS的效率,如果你對SAS中的DATA的步的原理更了解,那理解這些技巧是很容易的:
1.過濾數據
1)當你作數據預處理的時候,你可以會從一個很大的數據集中讀入一些數,形成子集。
則這個時候使用IF的效率就不如WHERE了。為什麼?因為IF的作用是把數據讀入PDV後再作判斷,而WHERE在數據讀入PDV之前就作判斷。
2)在PROC過程中的直接使用WHERE 條件來過濾數據。
3)對於從外部讀入的數據,如果需要過濾,則直接在這個變量讀入過程中加上相應的條件。
input x; if x>10; input y; 當X不滿足條件時候,則不再讀入後續數據。
2.生成數據
1)如果不要生成最終數據集,只是處理一個過程。建立多使用:data _null_;
2)合併二個數據集的時候,如果二個數據集相關,建議使用proc apend 過程;
data one;
set one two;
run;
---方法二隻是讀入TWO的數據併入到ONE中。
proc append base = one data = two;
run;
3)在SET 後面直接過濾不需要的變量(set test(keep=var1);) 可以避免不需要的變量進入PDV
4)建立索引。如果讀入大數據量的時候,可以在讀入的時候即為數據集加上索引,方便後續的高效訪問(data test (index=));)
5)預編譯
對於常用的生成數據過程,可以利用PGM的過程預編譯好,存儲起來,要使用時候,直接調用。可以節約編譯器時間。
例如:
DATA one2/ pgm = progname ;SET one;
RUN ;
DATA pgm= progname ;
RUN;
3.模糊匹配
1) is missing/is null 用於檢查字符變量是否為空或者數值變量是否缺失。
2)% 代表0個以上的任意個數的字符。
3)_(下劃線)僅代表一個任意字符。
4)contains ?是否包含某個字符 x ? 'afd' 相當於 x like '�d%';
1.SAS是一般統計分析人員處理大數據的較好選擇
在對大數據進行處理時,SPSS根本用不上,效率很低,而R軟體處理數據時是先把數據讀取到內存,當數據大小接近或超過內存大小時,R也無法應用。SAS是利用硬碟、運行效率較高的軟體,是比較好的選擇。
2. 測試集應用可檢驗程序是否正確,少做無用功
大數據的分析花費的時間比較長,計算一個頻率可能就需要花費半個小時以上,所以抽取一些case作為測試集,可檢驗程序準確性,提高運行效率。抽取數據的常用方法如:使用obs=option選項,proc surveyselect進行分層抽樣等。使用obs=option選項比較簡單,利用種子產生隨機數來抽取等等, 例如:
proc means data=test(obs=1000);
run;
或者
options obs=1000;
proc means data=test;
run;
options obs=max;
3.僅保留需要的變量,壓縮變量長度
數據集中只保留需要的變量,變量太多會影響效率,對於無關的變量可以drop掉,或者keep想要的變量。在data步中在set後面的數據集進行keep、drop,效率更高。
Data a;
Set b(keep=);
Run;
變量長度會影響數據大小,可使用proc contents查看變量長度,使用input或proc sql修改變量長度。
4. 在對符合已知變量條件的記錄進行處理時,果斷先進行篩選,然後在進行處理。同時在 Data步建立新數據集,在進行的條件篩選中,where的效率比if高,因為where在讀入的時候就已經進行判斷,而if則是等到全部讀完的時候才進行判斷。如需對class數據集中的男生建立一個新變量weight_new,以下這種寫法是不可取的。
data test;
set sashelp.class;
weight_new=sum(height,-101);
if sex=」男」;
run;
可以這麼寫
data test;
set sashelp.class(Where =(sex=」男」));
weight_new=sum(height,-101);
run;
5. 一些能省略的data步,如先經過data步進行簡單的條件篩選,然後進行proc步的一些操作,諸如此類的data步,儘量省略吧。
data test;
set sashelp.class;
where sex=」男」;
run;
proc means data=test;
var weight height;
run;
完全可以這麼寫
proc means data=test(where=(sex=」男」));
var weight height;
run;
6.需要修改數據集變量的label和format格式時,還是通過proc datasets過程進行修改效率比較快,它不需要記錄進入pdv,比起data步更有效率。
data test;
set sashelp.class;
label weight="體重(斤)";
format weight best6.2;
run;
proc datasets library=sashelp;
modify class;
label weight="體重(斤)";
format weight best6.2;
run;
quit;
7.縱向合併數據集時,如果生成的目標表就是來源表之一,那麼proc append會比data步更有效率。
data test1;
do i=1 to 10000000;
x=1;y=1;z=1;
output;
end;
run;
data test2;
do i=1 to 10000000;
x=1;y=1;z=1;
output;
end;
run;
data test1;
set test1 test2;
run;
/*proc append*/
data test1;
set test1;
stop;
run;
proc append base=test1 data=test2;
run;
/*proc datasets中的append*/
data test1;
set test1;
stop;
run;
proc datasets library=work;
modify test;
append base=test1data=test2;
run;
quit;
proc append和proc datasets中的append過程效率是一樣的。
8.使用optionscompress=yes可節省硬碟空間
對於大數據集,運行時,緩存的大小可達到原數據大小的10倍甚至更高,會導致硬碟空間不足,所以需要數據集壓縮,節省空間,sas裡可以通過options compress=yes來進行壓縮。
9.如果我們想要查看一個變量頂部5%的記錄,可以通過proc rank一步實現,而不需先通過univariate過程先將p95分位數求出,然後賦值給宏變量,最後再回到數據集中篩選。
data test;
do i=1 to 200;
output;
end;
run;
proc rank data=test groups=100 out=want(where=(i_pct>=95));
var i;
ranks i_pct;
run;
10.在編寫一些proc步時,對於分組變量最好是用class而不用by,因為用by是得對分組變量進行排序的。
11.視圖的應用。視圖是一個虛擬表,其內容由查詢定義。同真實的表一樣,視圖包含一系列帶有名稱的列和行數據。但是,視圖並不在資料庫中以存儲的數據值集形式存在。行和列數據來自由定義視圖的查詢所引用的表,並且在引用視圖時動態生成。所以視圖能夠節省大量的空間,同時因為它不是以存儲的形式存在,因此在一定程序上能夠提高運行效率。如對生成的數據集進行means過程
data test1/view=test1;
do i=1 to 30000000;
x=1;y=1;z=1;output;
end;
run;
proc means data=test1;
var i;
run;
data test2;
do i=1 to 30000000;
x=1;y=1;z=1;
output;
end;
run;
proc means data=test2;
var i;
run;
對比之下,我們可以看到視圖比起數據集將近節省了10秒。但是引用視圖的時候要注意,視圖的名字能夠覆蓋視圖的名字,但是它不能覆蓋數據集的名字,因此建立視圖的時候,不能存在跟視圖一樣名字的數據集,否則會報錯。同時,如果視圖的名字存在,再要建立同樣名字的數據集也是會報錯。
12.format格式數據集的引用。比如說在信用卡交易數據集,每天的交易量都是很大的,同時包括境內境外交易,這時就存在幣種轉換問題。一張交易量很大的表,和一張幣種匯率表,這時如果通過幣種去連接兩個數據集,首先得先對這兩個數據集按幣種排序,然後merge進行計算,當然有人想到直接用sql連接,不過這樣消耗時間也都是非常大的。這時候就可以先將匯率表做成format的數據集形式,到時就可以直接使用了。如
data rate;
input currency $ rate date yymmdd10.;
format date yymmdd10.;
cards;
USD 6.13 2013/6/11
EUR 8.14 2013/6/11
GBP 9.56 2013/6/11
JPY 5.80 2013/6/11
HKD 0.78 2013/6/11
;
run;
data trans;
input id currency money;
cards;
001 USD 200
002 GBP 100
003 USD 120
004 HKD 1000
005 EUR 300
;
run;
proc sort data=rate nodupkey;
by currency;
run;
data rate_format;
set rate end=last;
retain fmtname 'rate_fmt' type 'c';
rename currency=start rate=label;
drop date;
run;
/*options fmtsearch=(sashelp);*/
proc format library=work cntlin=rate_format;
run;
data trans_amt;
set trans;
rate=put(currency,$rate_fmt.);
money_to_rmb=money*rate;
run;
注意format數據集的地址,如果非work邏輯庫下,則需要加上這麼一句話options fmtsearch=(邏輯庫名稱);
13.將數據集載入內存。該方法減少數據集內存分配和釋放的次數,降低I/O處理量,提高SAS程序執行效率,但是相當消耗內存,需要確認系統有足夠多的內存資源,同時在使用完後,要記得釋放。具體形式如下
sasfile test2 load;/*將數據集test2載入內存*/
data test;
set test2;
run;
proc means data=test2;
run;
sasfile test2 close;/*將test2數據集從內存中釋放*/
14.hash的應用。在data步中使用hash對象,不但可以快速有效地檢索和讀取數據,還可以實現數據集merge的功能,從而減少排序時間,提高了數據處理的能力,相對於merge,hash的效率更高,但是同時也很消耗內存,因此一般都是把小表放進hash中。如用前面匯率進行幣種的連接
data test;
if _n_=0 then set rate;
if _n_=1 then do;
declare hash share(dataset:'work.rate');
share.definekey('currency');
share.definedata(all:'yes');
share.definedone();
call missing (of _all_);
end;
set Trans;
if share.find()=0;
run;
精品推薦:
乾貨|藥物臨床試驗基本流程(最全總結版)
乾貨|生物統計系列知識匯總
福利|專屬生物統計師的幾本經典書籍
收藏|E9:臨床試驗統計原則(另附中英文對照詞彙表)
法規|ICH-GCP中英文對照(最完整版)
免費領取臨床試驗數據管理與統計編程全套乾貨資料包
免費領取| 第二期|臨床試驗數據管理與統計編程全套資料包!
SAS初級編程系列視頻在線免費高清觀看(電腦版)
實用|藥物臨床試驗必備文件及相關管理要求
好書推薦|免費領取臨床試驗幾本經典書籍
腫瘤TNM分期法
CDISC-SDTM基本理論及實踐系列文章匯總
SAS編程應用及相關知識分享系列文章匯總
製藥聯盟者 好文推薦:
免費領取|生物製藥從業人員的全套資料大禮包!!!
福利來啦!製藥人必備的全套資料包
乾貨|常見的全套質量控制流程圖
限時領取|製劑技術百科全書第三卷【美】J.斯沃布裡克【美】J.C.博伊蘭主編
匯總 | FDA常用詞彙中英文對照
歡迎掃碼添加小編小唐微信邀您進行業高端學習交流群!!!
更多,更及時的乾貨內容,請加我們的微信公眾號:cdiscgroup,誠邀業內人士及機構向我們投稿。投稿郵箱:1589510961@qq.com
【免責聲明】文章為網絡整理,不代表cdiscgroup立場。如因作品內容、版權等存在問題,請於本文刊發30日內聯繫cdiscgroup進行刪除或洽談版權使用事宜。
法邁新媒體是國內一家面向製藥行業供應鏈綜合服務平臺,致力於服務全球製藥行業從業人員。以創新的互網+模式服務於行業用戶,形成以「資源整合,知識共享」為核心,微信公眾號矩陣、社群矩陣為分支的新媒體模式,力爭打造國內活躍和具影響力的專業化平臺!