ラベル proc format の投稿を表示しています。 すべての投稿を表示
ラベル proc format の投稿を表示しています。 すべての投稿を表示

ユーザー定義フォーマットの確認やオプションの確認など

自分用のメモです。

オプションとユーザー定義フォーマットを確認したい時にもう100回くらい、書き方忘れるのでここに書きます。

proc options define;
run;

で使用可能なオプションの説明がログに山ほどでる。

proc options option=firstobs define;
run;

とoption=オプション名で指定すればそのオプションだけ調べれる。

けど大体、ヘルプかリファレンスみるかwebで調べる方が詳しくわかる。


ユーザー定義フォーマットの中身を確認するfmtlibオプションを、いつも忘れるので。


proc format;
 value SEX 1='男'
           2='女';
run;

proc format lib=work fmtlib;  
run;









データセットに吐き出す場合は

proc format lib=work cntlout=A1;  
run;


データセットから呼び込む場合はcntlinで。


駒交換における得点計算プログラム_Formatプロシジャのinvalueで入力形式を作成して計算する話にかこつけて

【※注意】後で、SASの話も一応でてきますので、、


将棋において、なんの犠牲も払わずに、タダで相手の駒をとることができる状況はまれです。
序盤は特にそうですが、
例えば、相手の「銀」を取れる代わりに、自分の「桂馬」がとられるといったように、戦う以上、駒の交換は避けられません。
しかし、避けられないならば、できる限り、自分に得になって、相手に損になるように交換するのが、勝つための大原則です。

例えば、「歩」と「飛車」の交換であれば、明らかに「飛車」の方が価値が高いので、喜んで「歩」を差し出していいでしょう。

では、例えば、相手の「飛車」を取れる代わりに、こちらの「香車」と「桂馬」の2つを犠牲にしなければならない攻め方の場合、その交換を行うべきか、避けるべきかどちらでしょう?

当然、状況によって駒の価値は変わるので、答えはでませんが、単純化して考える方法として駒の得点化ということをよく言います。


谷川浩司九段の有名な点数化例では、以下の通りです。


飛=15点
竜=17点
角=13点
馬=15点
金=9点
銀=8点
成銀=9点
桂=6点
成桂=10点
香=5点
成香=10点
歩=1点
と金=12点

これをみると「香車」と「桂馬」の2つの点数の合計は11点、対して「飛車」は15点なので、積極的に交換してもよいという理屈になります。



さて、ここからはおまけみたいなもんですが、とりあえず、やっとSASの話です。

以下のようなデータセットがあったとします。

data TRADE;
SENTE='桂';GOTE='金';output;
SENTE='香';GOTE='銀';output;
SENTE='香';GOTE='';output;
SENTE='歩';GOTE='';output;
run;









変数名SENTEは「先手」、GOTEは「後手」です。
このように、交換対象の駒をオブザベーションごとにいれます。

今回は先手4枚と後手2枚の交換ですが、どっちが得をするかぱっとわかりますか??

SASに計算させたいのですが、これ文字なんで、そのままじゃどうしようもないわけです。
アプローチはたくさんありそうですが、今回はインフォーマットでいきましょう

proc format;
invalue  koma '飛'=15 '竜'=17 '角'=13 '馬'=15 '金'=9 '銀'=8 '成銀'=9
              '桂'=6 '成桂'=10 '香'=5 '成香'=10 '歩'=1 'と金'=12;
run;

として点数換算表をインフォーマットにしちゃいましょう!
valueステートメントはよく使いますが、invalueって個人的にはあまりつかわないので新鮮です。

あとはもう

proc sql;
 select sum(input(SENTE,koma.)) as SPOINT label='先手の駒の得点合計'
       ,sum(input(GOTE,koma.)) as GPOINT label='後手の駒の得点合計'
  from TRADE;
 quit;

なんでもいいんで計算しちゃえば










こんなアウトプットがでて、損とも得ともいえない交換ということがわかります。
でも、僕が先手ならこの交換は絶対やりますけどね。まあ目安です。

この得点化プログラム、将棋の際に是非使ってください。

遊びで作ったコードの方が、実戦的なものよりプログラム能力を上達させる効果があるというのが僕の持論(言い訳)です。






フォーマットを使って集計_マルチラベルフォーマットで連続量を任意の範囲で区切って集計

カテゴリ集計のやり方は様々ですが、連続量を任意の範囲で区切って集計する場合
フォーマットを使うと結構便利です。MULTILABEL FORMATを使えば、値の区間が重複している場合も別途に集計できて、気持ちいいです。

今、以下のように

data Q1;
call streaminit(2014131);
 do i=1 to 1000;
  X=rand('uniform');
  output;
 end;
drop i;
run;






















0から1の間に分布する1000個の値について

 0.2未満
 0.2以上0.6未満
 0.6以上
 0.5未満
 0.5以上

のカテゴリで区切って数を数えてと言われた場合

if X<0.2 then CATE=1; などなどデータステップで集計変数を定義してからプロシジャにかけてもいいですが、面倒です。

しかも区切る範囲がかぶっている(0.1という値は0.2未満で集計され、かつ0.5未満でも集計されなければならない)ので変数を分ける必要があります。

そんな時なら、例えば

proc format; 
value FREQF (multilabel) 
 low-<0.2='0.2未満'
 0.2-<0.6='0.2以上0.6未満'
 0.6-high='0.6以上'
 low-<0.5='0.5未満'
 0.5-high='0.5以上';
quit; 

のように区切る範囲をフォーマットで定義します。 (multilabel) を打てば値が重複していても
定義できます。

その上で

proc means data=Q1 MIN MAX ; 
class X /mlf; 
var X;
format X FREQF.; 
run; 

としてやれば













のように一気に集計できます。最小最大値は確認用にだしているだけです。

formatで指定することと、classステートメントに/mlfをつけることを忘れずに。