【Code Teaching】Data Step基礎語法 – 下

在上一篇文章中介紹了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)

於此增加實際使用方法

數值處理

SUMsum(Argu1, Argu2, …)加總所有參數
INTint(Argu)取整數
ROUNDround(Argu <, Rounding-unit>)四捨五入
FLOORfloor(Argu)傳回小於參數的最大整數值
CEILceil(Argu)傳回大於參數的最大整數值
ABSABS(value)取絕對值
DIVIDEDIVIDE(分母, 分子)除以某數後取商數
MODMOD(被除數dividend, 除數divisor)除以某數後取餘數
SQRTSQRT(value)取平方根
MAXMax(value1, value2, …, valuen)回傳最大值
MINMin(value1, value2, …, valuen)回傳最小值
NN(value1, value2, …, valuen)計算非Missing value的個數
NMISSNMISS(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;

文字處理

UPCASEupcase(Argu)傳回參數的大寫值
LOWCASElowcase(Argu)傳回參數的小寫值
SUBSTRsubstr(string, position <, length>)從第P位擷取L個字元
COMPRESScompress(source ,< characters> ,< modifier(s)>)刪除特定字元後回傳
TRANWRDtranwrd(source, target, replacement)以特定字元替換目標字元後回傳
CATXcatx(delimiter, Argu-1 <, … Argu-n>)刪除前導與尾隨空白後插入指定分隔符號回傳
CATScats(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;

搜尋

INDEXindex(source, excerpt)傳回source中符合excerpt字串的第一個位置
FINDfind(string, substring <, modifier(s)> <, start-position>)從指定的位置開始搜尋,傳回string中符合substring字串的第一個位置
SCANscan(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;

時間日期

TIMEtime()無需參數,傳回目前的時間
TODAYtoday()無需參數,傳回目前的日期
DATETIMEdatetime()無需參數,傳回目前的日期時間
DATEPARTdatepart(datetime)擷取日期時間的值後,回傳日期值
DAYday(date)回傳日期值的當月第N天
MONTHmonth(date)回傳日期值的當年第N個月
YEARyear(date)回傳日期值的N年(西元制)
MDYmdy(month, day, year)放入月、日、年的值後,回傳完整的日期值
INTCKINTCK(interval, start-date, end-date, <‘method’>)回傳兩個日期之間相差的間隔(年月日)
INTNXINTNX(interval, start-from, increment <, ‘alignment’>)回傳起始位置增加或減少N個間隔(年月日)的日期
YRDIFYRDIF(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

PUT(sourceformat.)

  • 將數值型變數轉為文字型變數儲存
  • 將日期的數值型變數依照格式轉為文字型變數儲存
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;

謝謝閱讀這篇文章,有問題歡迎在下方留言

Categories: Basic

Leave a reply

Your email address will not be published. Required fields are marked *