在上一篇文章中介紹了Data Step基礎語法的「建立資料」與「來源資料」兩個部分,這一篇就來介紹「基礎常用敘述句、函數及自動變數」以及「Implicit-Output敘述句」
常用敘述句
主要分享常用的Data Step敘述句用法,有特殊用法的會以主題式文章介紹(例:Do-Loop、IF-ELSE、Array等)
賦值敘述句
Assignment Statement,是在使用函數時最重要的敘述句,沒有之一
以「等號=」為主體,左側放的是要用來儲存的變數名稱,右側放的是要儲存到這個變數的值
- 以單引號或雙引號括弧的值會以文字型變數的格式儲存
- 未以單引號或雙引號括弧的值會以數值型變數的格式儲存
Data test;
Num=12345; /*Assignment statement1*/
String="Test String"; /*Assignment statement2*/
run;
KEEP敘述句
與Keep Data set option功能近似,用來保留指定的變數
放置位置不拘
差別在於
- Data敘述句的keep Data set option:在當前Data Step執行完後,最後要輸出資料集時才會保留指定的變數
- Set敘述句的keep Data set option:僅讀取指定的變數進到當前Data Step使用(讀取較少變數)
- Keep敘述句:在當前Data Step執行完後,最後要輸出資料集時才會保留指定的變數
Data test;
set sashelp.cars;
keep Origin Make MSRP;
run;
DROP敘述句
與Keep Data set option功能近似,用來刪除指定的變數
當同時使用KEEP敘述句與DROP敘述句時,DROP敘述句必優先於KEEP敘述句
放置位置不拘
差別在於
- Data敘述句的dropData set option:在當前Data Step執行完後,最後要輸出資料集時才會刪除指定的變數
- Set敘述句的drop Data set option:僅讀取指定以外的變數進到當前Data Step使用(讀取較少變數)
- drop敘述句:在當前Data Step執行完後,最後要輸出資料集時才會刪除指定的變數
Data test;
set sashelp.cars;
drop Origin Make MSRP;
run;
Label敘述句
為指定的變數增加標籤(SAS Base&EG需點選變數屬性;SAS Studio為切換欄位顯示標籤)
由Label關鍵字與1(多)個 variable=’變數標籤’所組成
放置位置會影響輸出資料集的變數順序
- 放置於set敘述句或input敘述句前,最後輸出資料集會先出現Label敘述句指定的變數,隨後才出現剩餘的變數
- 放置於set敘述句或input敘述句後,最後輸出資料集的變數會依照原本的順序出現
Data test;
set sashelp.cars;
label
Make='製造商'
Origin='產地'
MSRP='建議售價';
run;
Retain敘述句
排列最後輸出資料集的變數順序,依照Retain敘述句輸入順序顯示,未輸入的變數會依照原本順序顯示
必須放在set敘述句或input敘述句前才有效果
可搭配自動變數(_numeric_、_char_)使用
data test;
retain msrp invoice;
set sashelp.cars;
run;
Format | Informat敘述句
Format敘述句是用來調整輸出資料集最後的變數格式
比喻來說就是我們外出打扮後最後所看到的模樣
放置位置會影響輸出資料集的變數順序、但不影響效果,通常會放在set敘述句或input敘述句後方以避免調整到變數順序
data test;
format num1 z8. num2 best12.;
input str1 $ str2 $ num1 num2;
cards;
A1 CV 323 12
A2 BS 535 16
A3 SE 65 18
;
run;
Informat敘述句是當使用讀取Set敘述句或Input敘述句讀取資料集時,告訴SAS這個變數要以何種格式來讀取
比喻來說就是我們的著衣尺寸,30吋腰圍硬塞進尺寸S的褲子肯定是不行的吧 (ಥ﹏ಥ)
放置位置會影響輸出資料集的變數順序、但不影響效果,通常會放在set敘述句或input敘述句後方以避免調整到變數順序
data test;
informat num comma6. ;
input str1 $ str2 $ num;
cards;
A1 CV 32,312
A2 BS 53,516
A3 SE 62,518
;
run;
Length敘述句
調整新增文字型變數的長度,避免以較大的變數長度來儲存較少字元的值,增加I/O使用效率
放置位置必須在set敘述句或input敘述句前方
- 放在後方會出現warning、並且不具效果,此時的變數長度已被SAS宣告完成不能修改(但格式與標籤可以)
data test;
length short $10. long $20.;
input short $ long $;
cards;
abcdefghijk kjsldfjlksajlkefsdvz
;
run;
Rename敘述句
重新命名變數的名稱
放置位置不拘
data test;
set sashelp.cars;
rename
make=car_make
origin=car_origin
msrp=car_msrp;
run;
PUT敘述句
將資料或自訂文字寫到SAS LOG、或是使用File敘述句儲存到所指定的外部檔案位置
/*打印到SAS LOG*/
data _null_;
set sashelp.cars;
put 'Model: ' model;
run;
/*搭配File敘述句*/
data _null_;
file "C:\test.txt";
put 'This is a test string!';
run;
常用函數
以介紹日常進行資料處理會使用到的函數為主,先前文章簡單介紹過【05】資料處理必備 – Functions與Call Routines)
於此增加實際使用方法
數值處理
SUM | sum(Argu1, Argu2, …) | 加總所有參數 |
INT | int(Argu) | 取整數 |
ROUND | round(Argu <, Rounding-unit>) | 四捨五入 |
FLOOR | floor(Argu) | 傳回小於參數的最大整數值 |
CEIL | ceil(Argu) | 傳回大於參數的最大整數值 |
ABS | ABS(value) | 取絕對值 |
DIVIDE | DIVIDE(分母, 分子) | 除以某數後取商數 |
MOD | MOD(被除數dividend, 除數divisor) | 除以某數後取餘數 |
SQRT | SQRT(value) | 取平方根 |
MAX | Max(value1, value2, …, valuen) | 回傳最大值 |
MIN | Min(value1, value2, …, valuen) | 回傳最小值 |
N | N(value1, value2, …, valuen) | 計算非Missing value的個數 |
NMISS | NMISS(value1, value2, …, valuen) | 計算Missing value的個數 |
data test;
math_sum=sum(19, 81, 29, 64, 58); /*251*/
math_int=int(45.2136); /*45*/
math_round=round(29.8, 1); /*30*/
math_floor=floor(63.7); /*63*/
math_ceil=ceil(7.3); /*8*/
math_abs=abs(-7.2); /*7.2*/
math_divide=divide(120, 2); /*60*/
math_mod=mod(9, 2); /*1*/
math_sqrt=sqrt(14.4); /*3.7947331922 */
math_max=max(41, 98, 35); /*98*/
math_min=min(41, 98, 35); /*35*/
math_N=N(1, 3, ., 7, 9); /*4*/
math_NMISS=NMISS( ., 4, ., 8, 10); /*2*/
run;
文字處理
UPCASE | upcase(Argu) | 傳回參數的大寫值 |
LOWCASE | lowcase(Argu) | 傳回參數的小寫值 |
SUBSTR | substr(string, position <, length>) | 從第P位擷取L個字元 |
COMPRESS | compress(source ,< characters> ,< modifier(s)>) | 刪除特定字元後回傳 |
TRANWRD | tranwrd(source, target, replacement) | 以特定字元替換目標字元後回傳 |
CATX | catx(delimiter, Argu-1 <, … Argu-n>) | 刪除前導與尾隨空白後插入指定分隔符號回傳 |
CATS | cats(Argu-1 <, … Argu-n>) | 刪除前導與尾隨空白後回傳 |
data test;
str_upcase=upcase('abcde'); /*ABCDE*/
str_lowcase=lowcase('ABCDE'); /*abcde*/
str_substr=substr('123456789', 2, 4); /*2345*/
str_compress=compress('*><*>///<*>3<*', "*"); /*><>///<>3<*/
str_tranwrd=tranwrd('*><*>///<*>3<*', "*", "@"); /*@><@>///<@>3<@*/
str_catx=catx("~", ' AA', 'BB', 'CC '); /*AA~BB~CC*/
str_cats=cats(' 12345 '); /*12345*/
run;
搜尋
INDEX | index(source, excerpt) | 傳回source中符合excerpt字串的第一個位置 |
FIND | find(string, substring <, modifier(s)> <, start-position>) | 從指定的位置開始搜尋,傳回string中符合substring字串的第一個位置 |
SCAN | scan(string, count <, character-list <, modifier>>) | 傳回string中,依照character-list計數的第count個字元 |
data test;
string='This is a test sentence.';
search_index=index(string, 'test'); /*11*/
search_find=find(string, 'test'); /*11*/
search_scan=scan(string, 2, ' '); /*is*/
run;
時間日期
TIME | time() | 無需參數,傳回目前的時間 |
TODAY | today() | 無需參數,傳回目前的日期 |
DATETIME | datetime() | 無需參數,傳回目前的日期時間 |
DATEPART | datepart(datetime) | 擷取日期時間的值後,回傳日期值 |
DAY | day(date) | 回傳日期值的當月第N天 |
MONTH | month(date) | 回傳日期值的當年第N個月 |
YEAR | year(date) | 回傳日期值的N年(西元制) |
MDY | mdy(month, day, year) | 放入月、日、年的值後,回傳完整的日期值 |
INTCK | INTCK(interval, start-date, end-date, <‘method’>) | 回傳兩個日期之間相差的間隔(年月日) |
INTNX | INTNX(interval, start-from, increment <, ‘alignment’>) | 回傳起始位置增加或減少N個間隔(年月日)的日期 |
YRDIF | YRDIF(start-date, end-date, < basis>) | 回傳兩個日期之間相差的年 (常用來計算年齡) |
data test;
dt_time=time(); /*22:17:44*/
dt_today=today(); /*25NOV2024*/
dt_datetime=datetime(); /*25NOV24:22:17:44*/
dt_datepart=datepart( dt_datetime ); /*25NOV2024*/
dt_day=day('26Nov2024'd); /*26*/
dt_month=month('26Nov2024'd); /*11*/
dt_year=year('26Nov2024'd); /*2024*/
dt_mdy=mdy(11, 26, 2024); /*26NOV2024*/
dt_intck=intck('month', '02Feb2024'd, '15Jul2024'd); /*5*/
dt_intnx=intnx('year', '01Jan2011'd, 2); /*01JAN2013*/
dt_YRDIF=yrdif('08Jul2017'd, '26Feb2026'd, 'age'); /*8.6383561644*/
/*change format*/
format dt_time time. dt_today date9. dt_datetime datetime. dt_datepart date9. dt_mdy date9. dt_intnx date9.;
run;
格式轉換
Input | put 函數
Input function
INPUT(source, <? | ??> informat.)
將文字型變數轉為數值型變數儲存
data test;
str='984563123';
str_input=input(str, best12.);
run;
put function
- 將數值型變數轉為文字型變數儲存
- 將日期的數值型變數依照格式轉為文字型變數儲存
data test;
num1=5201314;
num1_put=put(num1, 7.); /*5201314*/
num2=25120;
num2_put=put(num2, date9.); /*10OCT2028*/
run;
自動變數
在執行Data Step(或在特定環境)時,SAS自動設定的變數,先前文章已介紹過前5個【03】資料處理須知|認識觀察值與變數,此次多介紹first.variable與last.variable
_N_
紀錄當前PDV資料集是第幾筆觀察值,第1筆即為1
Data _Null_;
input No $ Age;
put _N_ No= Age=;
cards;
1 19
2 23
3 17
4 21
5 22
;
run;
_ERROR_
紀錄目前程式執行過程出現的錯誤,0為無錯誤
Data _Null_;
input No $ Age;
put _N_= _Error_=;
cards;
1 DD
2 23
3 17
4 21
5 22
;
run;
_ALL_
等同於該資料集所有的變數,在需要針對所有變數或是將變數儲存至矩陣時很方便
Data test;
input No $ male $ female $;
put _all_;
cards;
1 Andy Viola
2 Jonny Aly
3 Nicola Melissa
;
run;
_Numeric_
等同於該資料集所有的數值型變數,在只需要針對數值型操作時很方便
Data test;
input No $ Score1 Score2;
array num_old{*} _Numeric_ ;
array num_new{*} new_Score1-new_Score2;
do i=1 to 2;
num_new[i]=num_old[i]+10;
end;
cards;
1 59 77
2 46 31
3 81 58
4 46 89
5 71 72
;
run;
_CHAR_ | _Character_
等同於該資料集所有的文字型變數,在只需要針對文字型操作時很方便
Data test;
input No $ male $ female $;
array char_old{*} $ _char_;
array char_new{*} $20 new_male new_female;
do i=1 to 2;
char_new[i]=cats("Prefix-", char_old[i], "-Suffix");
end;
cards;
1 Andy Viola
2 Jonny Aly
3 Nicola Melissa
;
run;
First.variable
當使用by敘述句排序時,SAS會自動為每個by敘述句以後變數組合的第一個值賦予1的值
data test;
set sashelp.cars;
by make;
if first.make=1 then make_first=1;
else make_first=0;
run;
Last.variable
當使用by敘述句排序時,SAS會自動為每個by敘述句以後變數組合的最後一個值賦予1的值
data test;
set sashelp.cars;
by make;
if last.make=1 then make_last=1;
else make_last=0;
run;
Implicit-Output敘述句
在每一次的Data Step迭代到達終點時,會自動將PDV的值寫入到資料集,此為Implicit-Output
儘管沒有顯示在語法中,但每個Data Step最後面都會自動代入Implicit-Output敘述句
data test;
set sashelp.cars;
/*Implicit-Output statement*/
run;
例外情形:使用output敘述句
Explicit-Output敘述句
顧名思義,就是在每個Data Step結束之前,增加任何一個Output敘述句到程式碼中,此時就不會有Implicit-Output敘述句,常與條件式敘述句搭配,用來控制想要的值到資料集
data test;
set sashelp.cars;
if origin='Asia' then output; /*僅輸出Origin='Asia'到test這個資料集*/
run;
謝謝閱讀這篇文章,有問題歡迎在下方留言