2018年7月19日 星期四

Non printable 字元

問題:有特殊 ASCII 字碼存在資料裡面,而且用 print 也看不見,會造成資料 compare 不一致,或者 ods 輸出會出現莫名的換行或符號
解決:
可以先了解有哪些 non-printable 的字碼,可參考
ascii-table

ASCII extended sets characters 有兩種編碼

  • 十進位編碼 0 to 255 (decimal values)
  • 六進位編碼 00 to FF (hexadecimal values)

但一般的 ASCII table (不含extended sets) 是 0 to 127
因此前 33 個 (0 to 32) and character 127 are the non-printable characters

例如: HT ( Horizontal Tabulation )
就是鍵盤上的 tab
用十進位編碼來看是 9 號,可按鍵盤 tab 或者 ALT 數字鍵盤9
用六進位編碼是 09 ,在 SAS 裡用 '09'x

反過來說,要看變項值的 Hexadecimal

data a; a='!'; put a= a hex. ; run; 

第一、要檢查出來

  • 用 sas function 的 NOTPRINT(string <,start>) 如果是 NOTPRINT 回傳 1

依SAS原廠的範例,來看 132, 127254 被 NOTPRINT 定義為 non-printable

data test; 
  do dec=0 to 255;  
    byte=byte(dec);  
    hex=put(dec,hex2.);  
    notprint=notprint(byte);  
    output;  
  end;  

proc print data=test; run;

ref: SAS(R) 9.2 Language Reference: Dictionary, Fourth Edition

  • 用 prxmatch 等搜尋去找。 regular expression 輸入 hexadecimal values 是用 \x00

    data test2; set test;
    byte_re=put(byte, $hex2.);
    kk=prxmatch("/00|01|02|03|04|05|06|07|08|09|0A/", byte_re);
    kk2=find(byte,'00'x);
    kk3=prxmatch("/[^\x00\t\x20-\x7E]/", byte); /自定義查找/
    run;

第二、進行轉換

  • translate 取代1個字,就會留下1個位置,即原本9個不能換成8個。
    更可以1次把多個字作取代 f2_translate=translate(f1,' ','000102030405060708090A'x);

  • tranwrd 類似 translate 但只能1次換1個。

  • transtrn 1次換1個,但可以原本9個換成8個。

    data example;
    length f1 f2_translate f3_tranwrd f4_transtrn $20;
    f1 = cat('Part1','0A'x,'Part2');
    f2_translate = translate(f1,' ','0A'x);
    f3_tranwrd = tranwrd(f1,'0A'x,' ');
    f4_transtrn = transtrn(f1,'0A'x,trimn(''));
    run;

ref: https://programmer-pro.com/special-character-sas-hex/

2018年6月12日 星期二

AUTOEXEC相關

說明:要調整 sas work library 的位置。

改變 work library 的實體位置

  • 直接在電腦左下「程式集」按右鍵修改 SAS 的捷徑,在最尾端加上 -WORK "d:\SAS Temporary Files"
  • 或是去改個人設定檔,先查設定檔在哪
    proc options option=config;run;
    查看 log 應可見 CONFIG=C:\Program Files\SASHome2\SASFoundation\9.4\nls\zt\sasv9.cfg 之類的
    用文字編輯器打開加入以下
    -WORK "d:\SAS Temporary Files"

上面 proc option 的地方,若想做成 macro variable 可用
%put %SYSFUNC( GETOPTION( CONFIG )) ;
想完整列出所有option 用
proc options host;run;

ref: SAS System Options by Category
http://support.sas.com/documentation/cdl/en/hostwin/69955/HTML/default/viewer.htm#n0qn87565ybxoun12srorc6xhpz5.htm


說明:建立一個program,把開啟SAS想要 pre-loading 的相關程式,都納入,方便管理

預載 program

  • 依前項 work 的改法加入

-AUTOEXEC "D:\99_Tool\OneDrive\SAS_self\mysas\AUTOEXEC.SAS"
可以查詢 proc options option=Autoexec; run;

  • 或是所有想載入的所有程式放進 AUTOEXEC.SAS 裡帶入
    %inc "program path" / source2 ;
    上面 source2 會把原本的程式 put 出來

ref: Store and Recall Macros with SAS Macro Libraries


說明:單純預載需要的 macro

預載需要的 macro 有以下方法

  1. 直接用 %inc
  2. 讀取 compiled sas macro
  3. Autocall library

1. 直接用 %inc
若是同 folder 多個以 sas as the file extension 的 program ,可以用

filename files "program folder";  
%include files(name_of_program 1);
%include files(name_of_program 2);

2. 讀取 compiled sas macro

第1.設定 System options to store 以及 Macro options to store ,做出 compiled sas macro , dlcreatedir 可用來建立 folder

options dlcreatedir mstored sasmstore=one;  
libname one "d:\test";  
%Macro DAY1() / store source des="a test for store macro";  
  %put 今日是 &sysdate;  
%Mend DAY1;  
%Macro DAY2() / store source des="a test for store macro";  
  %put 明日是 %sysfunc(intnx(DAY, "&sysdate"d ,1),DATE7.);  
%Mend DAY2;  

第2.下次要用時,也要設定 mstored sasmstore

libname one "d:\test";  
options mstored sasmstore=one;  
%DAY1();  
%DAY2();  

若有多個 lib 可以用

options mstored sasmstore=ALL_LIB;  
libname one "d:\test";  
libname two "d:\test\two";  
libname ALL_LIB (one two);  

第3.可用以下做個確認

proc catalog catalog=one.sasmacr; 
  contents; 
quit;

第4.這類 compiled sas macro ,可以用 %copy 在 log 取得原始碼

options mstored sasmstore=one;  
%copy DAY1 /source;  

3. Autocall library

第1.建立好自己的 macro ,並確認沒有 store source

%Macro DAY1() /  des="a test for store macro";
%put 今日是 &sysdate;
%Mend DAY1;

第2.設定 System option to recall

Options mautosource sasautos=one;  
filename one 'd:\test';   
*;   
%DAY1();    

這兒 macro 的 compile 是發生在第4行時(叫出來用),並存在WORK裡。前項 folder 之下所有 sas file 的 macro 都可直接呼叫。
注意,如果第一次呼叫失敗,修改好程式後,要把 sas 關了再開重跑。
所以若原本有 store source ,那就有額外 option 要處理,我猜測是 mstored sasmstore 以及 sasmstore 的 library 之類的。

第3. 多個位置的應用。用逗號或 space 分開

Options mautosource sasautos= (one,two) ;  
filename one 'd:\test';   
filename two 'd:\test\two';   
*;   
%DAY1();  
*;   
%DAY2();  

整體來說,前3個方法可以用在同1個 program 裡,它們的 search sequence 為

  1. current session 做出來的 (WORK.SASMACR) ,如 %inc 或當下寫的
  2. compiled sas macro
  3. Autocall library
  4. SASHELP

ref: Store and Recall Macros with SAS Macro Libraries


說明:單純預載需要的 format

預載 format

  • 用 %inc 來 reload
  • 不reload的方式

不reload的方式

第1.前次 format 再建立時要指定輸出的 LIBRARY

options dlcreatedir;  
libname one "d:\test";  
PROC FORMAT LIBRARY=one PAGE;
value $sex ‘M’=’Male’
           ‘F’=’Female’;
run;

那個 PAGE 是同時把 format print 出來看

第2.後續要用時

libname one "d:\test";  
proc format library=one; run;  

第3.如果想 check

proc catalog catalog=one.formats;  
  contents;  
quit;
proc format library = one.formats;
  select $sex;
run;

ref: Base SAS® 9.4 Procedures Guide,

2018年6月11日 星期一

建資料或讀資料

說明:資料本身有 contain semicolons

Use the DATALINES4 statement 範例如下

libname two "d:\test\two";  
filename file1 "d:\test\two\DAY1.sas";  
data a ;  
  length code $100.;  
  input code &  $ ;  
  file file1 ;  
  put code $ ;  
datalines4;  
%Macro DAY1() / store source des="a test for store macro";  
  %put 今日是 &sysdate;  
%Mend DAY1;   
;;;;   
run;  

input code & 這裡面的 & 很重要,沒放的話,遇到 space 就不讀了,變成
%Macro
%put
%Mend

ref: Store and Recall Macros with SAS Macro Libraries