スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

SAS:特殊文字を含んだ変数の取扱方法

変数名が[SHIN-HENSU]のように、特殊文字を含んでいる場合は、以下のように扱う。

rename 'SHIN-HENSU'n = SHIN_HENSU ;
('変数名'n というスタイル)

ちなみに蛇足ですが、AccessやSQLだと[SHIN-HENSU]でOK。

スポンサーサイト

SAS:処理時間を計るマクロ

SASのログでは、実際に処理時間にどれだけかかったかが分からない。
ので、SASの処理時間を計測するマクロ関数を自作した。
ちなみにパソコンの体内時計を使用しています。

/*------------------------*/
/*-- 使い方 --------------*/
/*------------------------*/
%Timer_Init ; *←自作:タイマーを初期化するための関数 *;

data aaa;
set bbb ;
run ;

%Timer_Stamp ; *←自作:Timer_Initを走らせてから何分経過したかをログに出す *;

data ccc;
set bbb ;
run ;
%Timer_Stamp ; *←連荘使いOK。この場合でもTimer_Initを走らせてからの時間を計測 *;


/*----------------------------------*/
/*-- 自作マクロ関数 ----------------*/
/*----------------------------------*/

* 初期化用 *;
%macro timer_init;
%global __hazime ;

data _null_;
stime=datetime();
call symput("__hazime",compress(put(stime,best.)));
run;
%mend;

* 計測用 *;
%macro timer_stamp;
data _null_;
etime=datetime();
stime=&__hazime.;
int=etime-stime;
put "*** 開始時刻:" stime datetime.;
put "*** 終了時刻:" etime datetime.;
put "*** 処理時間:" int time.;
run;
%mend;

SAS:Split関数もどき

SASで、VBAのSPLIT関数みたいなものを使いたく、SASのヘルプに聞いてみたが、存在しない模様。
その代わり、SCAN関数というものを教えてもらった。
これを使えばSPLIT関数に近いことができる。

SPLIT関数は、区切り文字で文字列を分解することに使える。

SCAN関数: 文字列から区切り文字を指定し、番号順に取り出す
書式: SCAN(,<何個目?>,"<区切り文字>")
--

*----------------------------------------------*
*-- 以下サンプルプログラム --------------------*
*----------------------------------------------*


%let keys = var1 var2 varX ;

/*-- マクロ変数へ出力 --------------*/
data _NULL_ ;
length ccc $1000. ccc2 $1000.;
ccc = "&keys." ;
do i=1 to length(ccc) ;
ccc2 = scan(ccc,i," ");
if ccc2="" then stop ;

n+1;
call symput("varn", compress(put(n,best.))) ;
call symput("var" || compress(put(i,best.)), compress(ccc2)) ;
end ;
run;
*-- チェック・・・マクロ変数をプット --*;
%macro chk;
%do i=1 %to &varn. ;
%put ***&&var&i..***;
%end ;
%mend ;
%chk ;


/*-- データセットへ出力 --------------*/
data tbl ;
length ccc $1000. ccc2 $1000.;
ccc = "&keys." ;
do i=1 to length(ccc) ;
ccc2 = scan(ccc,i," ");
if ccc2="" then stop ;
output ;
end ;

keep ccc2 ;
run;
proc print data=tbl;
run;

SAS:インデックスを消さずにデータ更新する方法

SASで、インデックスや主キーを消さずにデータ更新する方法。
SASにはMySQLのReplace文が無い。(Proc SQLでやってもだめだった)
AppendプロシージャとProc SQLのModifyでやるのも面倒くさい。

ということでSASのサポートに問い合わせてみたところ、以下のようなとっても分かりやすいサンプルを教えてくれたのでメモとして残します。

【インデックスを消さずにデータステップを回す方法】
→ MODIFYステートメントで解決!

/*---------------------------------------------*/
/*-- Sample Program ---------------------------*/
/*---------------------------------------------*/
/* マスターデータセット */
data data0(index=(key1 key2));
input key1 key2 $ value;
datalines;
1 A 100
2 A 200
3 A 300
;
run;

/* トランザクションデータセット */
data data1;
input key1 key2 $ value;
datalines;
3 A 0.01
4 A 0.02
5 A 0.03
;
run;

data data0;
modify data0 data1(rename=(value=temp));*key以外で重複する変数名は一旦リネームする必要がある*;
by key1 key2;
select (_iorc_);*存在する/しないをコントロールするシステム変数*;
/* データが存在する場合、「書き換え」する */
when (%sysrc(_sok)) do;
value=temp;
replace;
end;
/* データが存在しない場合、「追加」する */
when (%sysrc(_dsenmr)) do;
value=temp;
output;
_error_=0;
end;
otherwise do;
put '予期せぬ I/O エラー';
_error_=0;
stop;
end;
end;
run;
/*---------------------------------------------*/

○参考資料
[Modifying a Master Data Set with Observations from a Transaction Data Set]
http://support.sas.com/documentation/cdl/en/basess/58133/HTML/default/a001772743.htm

SASのインデックスに関して

SASのインデックスに関するまとめ


■質問1
1.単一インデックスと複合インデックスの違い
 単一インデックスの違いと、複合インデックスの違いは?
 また、それぞれのメリット、デメリットは?

■回答1
単一インデックスは1つの変数に対して作成されるインデックスです。この時インデックス名は変数名と同一である必要があります。複合インデックスは複数の変数名に対して定義されるインデックスになります。複合インデックスの名前は変数名とは別の名前を定義します。

単一インデックスはSQL文が以下のいずれかの条件を満たした場合に使用されます。

1. 比較演算子を使用している
例)
where year > 2000;

2. 比較演算子の否定を使用している
例)
where actual ^> predict;

3. CONTAINS演算子を使用している
例)
where state contains 'North';

4. コロンモディファイアを使用した比較演算を使用している
例)
where state =: 'North';

5. TRIM関数を使用している
例)
where trim(state) = 'North Carolina';

6. BETWEEN演算子やAND演算子、比較演算子を使用して範囲指定をしている
例)
where 1999 < year < 2005;
where year between 1999 and 2005;

7. 「LIKE」、「NOT LIKE」演算子を使用している
例)
where sate like 'North %';
where country like '%Republic%';

8. IS MISSING、IS NULL演算子を使用している
例)
where county is missing;
where county is null;

9. SUBSTR関数を使用している
例)
where substr(state,1,5) = 'North';

10. IN演算子を使用している
例)
where product in ('BED','CHAIR');

11. OR演算子を同じ変数を複数回指定して使用している
例)
where product = 'BED' or product = 'CHAIR' or product = 'DESK';

12. eqt(Equal to Truncated string)演算子を使用している
例)
where state eqt 'New';

13. WHERE条件にて上記演算子をAND演算子を使用して複合的に使用している
例)
where (product in('BED','CHAIR')) and (county is missing);

複合インデックスはWHERE条件にて複数の変数を指定する場合に有効です。 例えば、下の例のようにWHERE条件で変数A、B、Cに常にアクセスするSQL文が発行される場合は、変数A、B、Cすべてを指定した複合インデックスを指定することで該当するSQLクエリのパフォーマンスが改善されます。

例) select * from test where A="a" and B="b" and C="c";

但し、複合インデックスには制約条件がございます。ご使用される場合は発行するSQLがこれらの条件を満たすかどうかご注意ください。

1. SQL文のWHERE条件では少なくともインデックスにて定義している先頭の二つのキー変数を使用している。
2. 複数の条件を指定する場合はAND条件を使用している。
3. 少なくとも条件文の1つにはEQ、またはIN記述子を使用している。

■質問2
 Proc SQLのCreate Indexで作成する場合は“複合インデックスになる”?

■回答2
上記の回答1の通り、単一の変数、複数の変数をインデックスに指定するかによって単一インデックス、複数インデックスが作成されます。create index ステートメントにて単一インデックス、複数インデックスを作成する例を以下に記載致しましたので、ご確認頂けますでしょうか。

単一インデックスの例:

/* データセット */
data test;
set sashelp.class;
run;

/* 複合インデックス */
proc sql;
create index sex on work.test;
quit;


複合インデックスの例:

/* データセット */
data test;
set sashelp.class;
run;

/* 複合インデックス */
proc sql;
create index cmpidx on work.test(sex,age) ;
quit;

■質問3
2.データステップでインデックスが消えるかどうか
たとえば、データセット[test]にインデックスを付与した後、以下のようなデータステップを実行した場合、インデックスは消える?
data test;
merge test(IN=A) test2(IN=B);
by ID;
if A ;
run;

 また、次のデータステップではインデックスは消えない?
proc append base=test data=test2 force ;
run;

■回答3
DATAステップのSETステートメントやMERGEステートメントにてデータセットを作成する場合、データセットを新規に作成します。そのため、頂きましたサンプルの場合、「work.test」という名前の新しいデータセットが新規に作成されるため、インデックスは作成されません。
APPENDプロシジャはBASEオプションに指定したデータセットにDATAオプションに指定したデータセットの内容を追加します。そのため、作成されたインデックスは削除されません。

■質問4
3.インデックスの削除方法
 インデックスの消去方法は?

■回答4
インデックスを削除するにはDROP INDEX文にて以下のように記述します。

drop index <インデックス名> from ※(変数名1,変数名2,...,変数名n);
※複合インデックスの場合は()に変数名を指定します。

/* 単一インデックス */
proc sql;
create index sex on work.test;
drop index sex from work.test;
quit;

/* 複合インデックス */
proc sql;
create index cmpidx on work.test(age,sex);
drop index cmpidx from work.test;
quit;



上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。