ラベル [▼ SAS遊び の投稿を表示しています。 すべての投稿を表示
ラベル [▼ SAS遊び の投稿を表示しています。 すべての投稿を表示

2023年1月1日日曜日

SASで年賀状2023

 



SASで年賀状をつくりました(ほぼ「SASで年賀状」の焼き直し)
2023年もどうぞよろしくお願いいたします!





年賀状をつくるプログラム (SAS9.4M7で動作確認)

*** 描画用のパーツ ;
data rabbit;
  x1= 0;     y1= 0;
  x2= 0;     y2=-6.5;
  x3=-0.31;  y3= 1.2;
  x4= 0.31;  y4= 1.2;
  x5= 0;     y5= 0.15;
  x6= 0;     y6= 0.7;
  x7=-0.5;   y7= 5;
  x8= 0.5;   y8= 5;
  x9=-0.5;   y9= 5.5;
  x10=0.5;   y10=5.5;
  x11=-0.8;  y11=0.1;
  x12=0.8;   y12=0.1;
run;

*** 描画 ;
title ;
ods graphics on / height=10cm width=14.8cm;

proc sgplot data=rabbit noautolegend;
 styleattrs wallcolor=khaki;
   
 /* Text */
 inset "HAPPY NEW YEAR"  /  position=top textattrs=(color=brown size=31cm);
 inset "20"  /  position=bottomleft textattrs=(color=brown size=140cm );
 inset "23"  /  position=bottomright textattrs=(color=brown size=140cm );
   
 /* rabbit */
 scatter x=x1 y=y1  /  markerattrs=(symbol=circlefilled  size=3cm color=white);
 scatter x=x2 y=y2  /  markerattrs=(symbol=circlefilled  size=4cm color=white);
 scatter x=x3 y=Y3  /  markerattrs=(symbol=circlefilled  size=0.2cm color=black);
 scatter x=x4 y=Y4  /  markerattrs=(symbol=circlefilled  size=0.2cm color=black);
 scatter x=x5 y=y5  /  markerattrs=(symbol=ArrowDown  size=0.5cm color=black);
 scatter x=x6 y=y6  /  markerattrs=(symbol=TriangleDownFilled  size=0.2cm color=black);
 scatter x=x7 y=y7  /  markerattrs=(symbol=CircleFilled  size=1cm color=white);
 scatter x=x8 y=y8  /  markerattrs=(symbol=CircleFilled  size=1cm color=white);
 scatter x=x9 y=y9  /  markerattrs=(symbol=CircleFilled  size=1cm color=white);
 scatter x=x10 y=y10  /  markerattrs=(symbol=CircleFilled  size=1cm color=white);
 scatter x=x7 y=y7  /  markerattrs=(symbol=CircleFilled  size=0.7cm color=mistyrose);
 scatter x=x8 y=y8  /  markerattrs=(symbol=CircleFilled  size=0.7cm color=mistyrose);
 scatter x=x9 y=y9  /  markerattrs=(symbol=CircleFilled  size=0.7cm color=mistyrose);
 scatter x=x10 y=y10  /  markerattrs=(symbol=CircleFilled  size=0.7cm color=mistyrose);
 scatter x=x11 y=y11  /  markerattrs=(symbol=CircleFilled  size=0.4cm color=pink);
 scatter x=x12 y=y12  /  markerattrs=(symbol=CircleFilled  size=0.4cm color=pink);

 xaxis min=-3 max=3  display=none;
 yaxis min=-5 max=1  display=none;
run;


2022年6月29日水曜日

SASで花火を描く




暑中お見舞い申し上げます。




SASで花火描いてみました。三角関数をつかってるだけの単純なプログラムです。

/* 花火描画用データ */
data fireworks;
 rad = constant('pi')/180;
 call streaminit(777);
 do i = 1 to 5;
  xpos = rand("uniform",-30,30);
  ypos = rand("uniform",-30,30);
  do rmax = 0, 36;
  do r = 0 to rmax by 4;
  do a = 0 to 360 by 15;
    x=cos(a*rad)*r+xpos;
    y=sin(a*rad)*r+ypos;
    output;
  end;
  end;
  end;
 end;
run;

/* 花火描画 */
title;
ods graphics / height=20cm width=20cm;

options animation=start animduration=1.2 printerpath=gif;
ods noresults;
ods printer file="出力するGIFファイルのフルパスをここに指定。ファイル名は「fireworks.gif」とか適当に" ;

%macro m_fireworks(i=,color=);
 proc sgplot data=fireworks aspect=1 noautolegend;
  styleattrs wallcolor=midnightblue;
  scatter x=x y=y / markerattrs=(symbol=circlefilled color=&color size=0.1cm );
  xaxis min=-50 max=50 display=none;
  yaxis min=-50 max=50 display=none;
  inset "Summer Greetings to All."/ position=bottom textattrs=(color=lightblue size=25cm family="Arial");
  by rmax;
  where i=&i;
 run;
%mend;
%m_fireworks(i=1,color=yellow);
%m_fireworks(i=2,color=skyblue);
%m_fireworks(i=3,color=lightgreen);
%m_fireworks(i=4,color=yellow);
%m_fireworks(i=5,color=lightpink);

ods printer close;
ods results;
options animation=stop;

ods graphics / reset=all;


2021年4月4日日曜日

SASで囲碁盤を再現。



ステイホーム中に囲碁を勉強し始めました。

ルールやっと覚えたところで、コンピュータの一番弱い設定のやつに勝ったり負けたりのレベルですが。。強くなって碁盤の上で繰り広げられる熱い戦いを理解できるようになっていきたいです。


てことで、SASで囲碁を再現してみたくなったので勢いで書いてみました。プログラムは勢いで適当に書いたので、ひどい感じです。


/*** 碁石の位置 (y軸は碁盤に合わせて逆に指定[上から1,2,3...]) *******/
data pos;
input black_x black_y_reverse white_x white_y_reverse;
cards;
2 2 8 2
2 8 3 8
3 7 . .
;

/*** 碁盤の線 *********/
data line;
 do line_x=1 to 9;
 do line_y_reverse=1, 9;
   line_grp=10+line_x;
   output;
 end;
 end;
 do line_y_reverse=1 to 9;
 do line_x=1, 9;
   line_grp=20+line_y_reverse;
   output;
 end;
 end;
run;

data igo;
 set line pos;
run;

/*** PLOT *******************/
proc template ;
 define statgraph tmpl_igo ;
   begingraph;

     layout overlay /
        wallcolor=CXFFC864 /* 碁盤の色 */
        aspectratio=1
        xaxisopts=( display=none displaysecondary=(line ticks tickvalues)
                    linearopts=( viewmin=1 viewmax=9
                                 tickvaluesequence=(start=1 end=9 increment=1) ) )
                                  
        yaxisopts=( reverse=true /* y軸の数値の順番を逆 [上から下] にする) */
                    display=(line ticks tickvalues)
                    linearopts=( viewmin=1 viewmax=9
                                 tickvaluesequence=(start=1 end=9 increment=1)
                                 tickdisplaylist=( "一" "二" "三" "四" "五" "六" "七" "八" "九") ) );

        /* 碁盤の線 */
        seriesplot x=line_x y=line_y_reverse / group=line_grp lineattrs=(color=black pattern=solid);
        
        /* 碁石(黒)を配置 */
        scatterplot x=black_x y=black_y_reverse /
                       filledoutlinedmarkers=true
                       markerfillattrs=(color=black) 
                       markeroutlineattrs=(color=black thickness=1)
                       markerattrs=(symbol=circlefilled size=40 )
                       dataskin=matte;

        /* 碁石(白)を配置 */
        scatterplot x=white_x y=white_y_reverse /
                       filledoutlinedmarkers=true
                       markerfillattrs=(color=white) 
                       markeroutlineattrs=(color=gray thickness=1)
                       markerattrs=(symbol=circlefilled size=40 )
                       dataskin=matte;
        
     endlayout;

   endgraph;
 end;
run;

proc sgrender data=igo template=tmpl_igo;
run;




2020年1月1日水曜日

SASで年賀状





すべてのSASユーザーへ、SASで年賀状をつくりました。
2020年もどうぞよろしくお願いいたします!




年賀状をつくるプログラム (SAS9.4以上で動作)

*** 描画用のパーツ ;
data mouse;
  x1= 0;     y1= 0;
  x2= 0;     y2=-6.5;
  x3=-0.31;  y3= 1.2;
  x4= 0.31;  y4= 1.2;
  x5= 0;     y5= 0.15;
  x6= 0;     y6= 0.7;
  x7=-1.1;   y7= 4.5;
  x8= 1.1;   y8= 4.5;
run;

data whisker;
input higeno x9 y9;
cards;
1 -1.5  1.3
1 -0.8  1.1
2 -1.5  0.6
2 -0.8  0.6
3 -1.5 -0.1
3 -0.8  0.1
4  1.5  1.3
4  0.8  1.1
5  1.5  0.6
5  0.8  0.6
6  1.5 -0.1
6  0.8  0.1
;

data tail;
input x10 y10;
cards;
1.45 -9.5
1.8  -8
2    -5
1.9  -2
;

data nenga;
 merge mouse whisker tail;
run;

*** 描画 ;
title ;
ods graphics on / height=10cm width=14.8cm;

proc sgplot data=nenga noautolegend;
 styleattrs wallcolor=lavenderblush;
   
 /* Text */
 inset "HAPPY NEW YEAR"  /  position=top textattrs=(color=gold size=31cm);
 inset "20"  /  position=bottomleft textattrs=(color=green size=140cm );
 inset "20"  /  position=bottomright textattrs=(color=orange size=140cm );
   
 /* mouse */
 scatter x=x1 y=y1  /  markerattrs=(symbol=circlefilled  size=3cm color=skyblue);
 scatter x=x2 y=y2  /  markerattrs=(symbol=circlefilled  size=4cm color=skyblue);
 scatter x=x3 y=Y3  /  markerattrs=(symbol=circlefilled  size=0.2cm color=black);
 scatter x=x4 y=Y4  /  markerattrs=(symbol=circlefilled  size=0.2cm color=black);
 scatter x=x5 y=y5  /  markerattrs=(symbol=ArrowDown  size=0.5cm color=black);
 scatter x=x6 y=y6  /  markerattrs=(symbol=TriangleDownFilled  size=0.3cm color=pink);
 scatter x=x7 y=y7  /  markerattrs=(symbol=CircleFilled  size=1.5cm color=skyblue);
 scatter x=x8 y=y8  /  markerattrs=(symbol=CircleFilled  size=1.5cm color=skyblue);
 scatter x=x7 y=y7  /  markerattrs=(symbol=CircleFilled  size=1.2cm color=lightpink);
 scatter x=x8 y=y8  /  markerattrs=(symbol=CircleFilled  size=1.2cm color=lightpink);

 /* wisker */
 series  x=x9 y=y9  /  group=higeno lineattrs=(color=black);

 /* tail */
 series  x=x10 y=y10  /  lineattrs=(color=lightpink thickness=0.12cm) smoothconnect;

 xaxis min=-3 max=3  display=none;
 yaxis min=-5 max=1  display=none;
run;




2018年12月28日金曜日

SASで雪だるまを描く




2018年も本ブログを見て頂いた方、コメントしてくださった方、どうもありがとうございました!
来年もどうぞよろしくお願いいたします!!

SASでグリーティングカードを作ってみました。


以下が今回作ったプログラムです。SAS9.4以降で動作します。
*** 描画用データ作成 ;
data SNOW;
  * ゆきだるま描画用データ作成 ;
  retain x1  0  y1  0;
  retain x2  0  y2 -6.5;
  retain x3 -1  y3 1;
  retain x4  1  y4 1;
  retain x5  0  y5 0;
  retain x6  0  y6 0.5;
  retain x7  0  y7 5.5;
  retain x8  0  y8 7;

  * ゆき描画用データ作成 ;
  call streaminit(777);
  do scene=1 to 5;
     do snow_x = -10 to 10 by 1;
        snow_y = rand('uniform')*30-15;
        output;
     end;
  end;
run;

*** 描画 ;
title ;
options  ANIMATION=START  ANIMDURATION=1   PRINTERPATH=GIF ;

ods noresults;
ods printer file="出力するパスを指定\test.gif";
ods graphics on / height=4in width=4in;

%macro ANIMATION;
  %do i=1 %to 5;
  proc sgplot data=SNOW noautolegend;
     where scene=&i;
     styleattrs wallcolor=skyblue;
     symbolchar name=SNOW char='2744'x;
     scatter x=snow_x y=snow_y /  markerattrs=(symbol=SNOW  size=1.5cm color=white);
     scatter x=x1 y=y1  /  markerattrs=(symbol=circlefilled  size=3cm color=white);
     scatter x=x2 y=y2  /  markerattrs=(symbol=circlefilled  size=4cm color=white);
     scatter x=x3 y=Y3  /  markerattrs=(symbol=circlefilled  size=0.2cm color=black);
     scatter x=x4 y=Y4  /  markerattrs=(symbol=circlefilled  size=0.2cm color=black);
     scatter x=x5 y=y5  /  markerattrs=(symbol=ArrowDown  size=0.5cm color=black);
     scatter x=x6 y=y6  /  markerattrs=(symbol=TriangleDownFilled  size=0.3cm color=orange);
     scatter x=x7 y=y7  /  markerattrs=(symbol=TriangleFilled  size=1.2cm color=red);
     scatter x=x8 y=y8  /  markerattrs=(symbol=CircleFilled  size=0.6cm color=white);
     inset "Happy Holidays"  /  position=top textattrs=(color=green size=35cm family='Arial');
     xaxis min=-3 max=3  display=none;
     yaxis min=-5 max=1  display=none;
  run;
  %end;
%mend;

%ANIMATION;

ods graphics on / reset=all;
ods printer close ;
ods results;

options  ANIMATION=STOP ;


2018年3月13日火曜日

SASでトランプを作る



SGPLOTでトランプ作ってみました。

以下のような感じで1枚ずつ、マーク4種類 × 数字13枚 = 52枚のトランプがグラフとして出力されます。


出力結果の一部を切り貼りした寄せ集め



プログラム


※SAS9.4で動作します。バージョンや環境などで結果が綺麗に出力されないとかあるかもしれません。

ハッキリいってプログラムとしては汚いです。とりあえず作ったって感じです。
あとジョーカーを含めるとプログラムが複雑になっちゃうので、やめました。やるとしたらsymbolimageステートメントとか使って好きな画像をトランプの絵柄にしてジョーカーにする感じになります。


/*** トランプの数字とマークの表示位置をデータ化 ***/
data CARD;
    input SYMBOL:$7. NUMBER:$5. X Y;
    TOP_X     = 1.5;
    TOP_Y1    = 14;
    TOP_Y2    = 12.5;
    BOTTOM_X  = 3.5;
    BOTTOM_Y1 = 0;
    BOTTOM_Y2 = 1.5;
cards;
symbol1 1  2.5  7
symbol1 2  2.5  12
symbol2 2  2.5  2
symbol1 3  2.5  12
symbol2 3  2.5  2
symbol1 3  2.5  7
symbol1 4  2    12
symbol2 4  2    2
symbol1 4  3    12
symbol2 4  3    2
symbol1 5  2    12
symbol2 5  2    2
symbol1 5  3    12
symbol2 5  3    2
symbol1 5  2.5  7
symbol1 6  2    12
symbol2 6  2    2
symbol1 6  3    12
symbol2 6  3    2
symbol1 6  2    7
symbol1 6  3    7
symbol1 7  2    12
symbol2 7  2    2
symbol1 7  3    12
symbol2 7  3    2
symbol1 7  2    7
symbol1 7  3    7
symbol1 7  2.5  9.5
symbol1 8  2    12
symbol2 8  2    2
symbol1 8  3    12
symbol2 8  3    2
symbol1 8  2    7
symbol2 8  2.5  4.5
symbol1 8  3    7
symbol1 8  2.5  9.5
symbol1 9  2    12
symbol2 9  2    2
symbol1 9  2.5  6.999
symbol1 9  2    8.666
symbol2 9  2    5.333
symbol1 9  3    8.666
symbol2 9  3    5.333
symbol1 9  3    12
symbol2 9  3    2
symbol1 10 2    12
symbol2 10 2    2
symbol1 10 2.5  10.333
symbol2 10 2.5  3.666
symbol1 10 2    8.666
symbol2 10 2    5.333
symbol1 10 3    8.666
symbol2 10 3    5.333
symbol1 10 3    12
symbol2 10 3    2
symbol1 J  2.5  10
symbol1 J  3    10
symbol1 J  2.8  7.5
symbol1 J  2.8  5
symbol1 J  2.4  3.5
symbol1 J  1.9  4.5
symbol1 Q  2    10.5
symbol1 Q  2.5  11
symbol1 Q  3    10.5
symbol1 Q  3.2  8.5
symbol1 Q  3.2  6.5
symbol1 Q  3.05 3.85
symbol1 Q  2.5  4
symbol1 Q  2    4.5
symbol1 Q  1.8  6.5
symbol1 Q  1.8  8.5
symbol1 Q  2.75 5.8
symbol1 K  2    10.5
symbol1 K  2    8
symbol1 K  2    5.5
symbol1 K  2    3
symbol1 K  3    10.5
symbol1 K  2.8  8
symbol1 K  2.6  5.3
symbol1 K  3    3
;


/*** マーク別に1~Kまでのトランプを作成 ***/
%macro trump( unicode=, color= );


/* Attribute Map */
data MYMAP;
     ID="myid";
     VALUE="symbol1"; MARKERCOLOR="&color"; MARKERSYMBOL="symbol1"; output;
     VALUE="symbol2"; MARKERCOLOR="&color"; MARKERSYMBOL="symbol2"; output;
run;


/* Plot */
proc sgplot data=CARD noautolegend dattrmap=MYMAP;
     by NUMBER notsorted;

     xaxis min=-1 max=5   display=none;
     yaxis min=-1 max=15  display=none;

     /* トランプの形に線を引く */
     refline 1.2 3.8  / axis=x;
     refline -1 15 / axis=y;

     /* トランプのマークをUnicodeで取得 */
     symbolchar name=symbol1  char=&unicode;
     symbolchar name=symbol2  char=&unicode / rotate=180;

     /* トランプの左上の数字とマークをPlot */
     text    x=TOP_X    y=TOP_Y1    text=NUMBER  / textattrs=(size=0.6cm color=&color) ;
     scatter x=TOP_X    y=TOP_Y2                 / markerattrs=(symbol=symbol1 size=1.3cm color=&color);

     /* トランプの右下の数字とマークをPlot */
     text    x=BOTTOM_X y=BOTTOM_Y1 text=NUMBER  / textattrs=(size=0.6cm color=&color)  rotate=180 ;
     scatter x=BOTTOM_X y=BOTTOM_Y2              / markerattrs=(symbol=symbol2 size=1.3cm color=&color) ;

     /* トランプの真ん中のマークをPlot */
     scatter x=X        y=Y                      / attrid=myid  markerattrs=(size=2.1cm) group=symbol;

run;

%mend;

%trump( unicode='2660'x, color=black )  /* スペード */
%trump( unicode='2663'x, color=black )  /* クラブ */
%trump( unicode='2665'x, color=red   )  /* ハート */
%trump( unicode='2666'x, color=red   )  /* ダイヤ */




2017年12月25日月曜日

SASでクリスマスカードを作る。



ぎりぎり間に合った・・・。
SASでクリスマスカード作ってみました。やっつけ仕事みたいにすごいシンプルですが。



























以下がプログラムです。
SAS9.4で動作します。あとHTML出力がONになっている前提です。

*** 描画用データ作成 *********;
* ツリー部分 ;
data DT1;
input X Y;
cards;
0 30
50 30
50 50
10 50
35 80
20 80
40 100
30 100
45 120
40 120
60 150
80 120
75 120
90 100
80 100
100 80
85 80
110 50
70 50
70 30
125 30
210 30
;
run;

* 星部分 ;
data DT2;
  call streaminit(201712);
  do X2=0 to 210 by 10;
    STAR = rand('uniform')*180;
    output;
  end;
run;

data DT3;
  set DT1 DT2;
run;


*** 描画 ******************;
proc sgplot data=DT3 noautolegend ;
   styleattrs wallcolor=black;
   series x=X y=Y / lineattrs=(thickness=7 color=white);
   scatter x=X2 y=STAR / markerattrs=(symbol=star size=0.6cm color=yellow);
   xaxis min=0 max=210;
   yaxis min=0 max=180;
   inset "Happy Holidays" / position=right textattrs=(color=white size=30cm);
run;



今年はあと1回記事書くか、書かないかって感じですが、あとちょっとで2018年ですね。
お疲れさまでした。

ブログに立ち寄っていただいたり、直接アイディアを頂いたり、みなさん有難う御座いました。
良い年末年始をお過ごしください!!

2016年12月19日月曜日

SASでクリスマスツリーを描画する2


去年書いた記事 「SASでクリスマスツリーを描いてみる」 を少し進化させてみました。
雪だるまと雪をunicodeで取得して、雪をチラチラさせるアニメーションを追加しました。




以下「The DO Loop」という有名なSASブログでも雪が舞い落ちるアニメーションをSASで作るプログラムを公開していて、面白いです。
「Animate snowfall in SAS」
http://blogs.sas.com/content/iml/2016/12/14/animate-snow-sas.html

今回こちらとちょっと内容被っちゃった上、私のやつの方がショボイです。。


以下が今回作ったプログラムです。一応SAS9.4で動作します。
*** ツリーとゆき描画用データ作成 ;
data SNOW;
  *** ツリー描画用データ作成 ;
  retain X1 0 Y1 1 Y2 0 Y3 -1 Y4 -2 Y5 -4;

  *** ゆき描画用データ作成 ;
  call streaminit(777);
  do scene=1 to 10;
     do X2=-3.5 to 3.5 by 0.2;
        SNOW = rand('uniform')*8-4;
        output;
     end;
  end;
run;


*** 描画 ;
title ;
options  ANIMATION=START  ANIMDURATION=0.5   PRINTERPATH=GIF ;
ods noresults;
ods printer file="出力先のパスを指定\test.gif" ;

%macro ANIMATION;
  %do i=1 %to 10;
  proc sgplot data=SNOW noautolegend;
     where scene=&i;
     styleattrs wallcolor=black;
     symbolchar name=SNOW char='2744'x;
     scatter x=X1 y=Y1 /  markerattrs=(symbol=starfilled size=0.8cm color=yellow);
     scatter x=X1 y=Y2 /  markerattrs=(symbol=trianglefilled size=1cm color=green);
     scatter x=X1 y=Y3 /  markerattrs=(symbol=trianglefilled size=2cm color=green);
     scatter x=X1 y=Y4 /  markerattrs=(symbol=trianglefilled size=3cm color=green);
     scatter x=X1 y=Y5 /  markerattrs=(symbol=squarefilled size=0.6cm color=brown);
     scatter x=X2 y=SNOW / markerattrs=(symbol=SNOW size=1.5cm color=white);
     inset "Happy Holidays(*ESC*){unicode '2603'x}"/ position=bottom textattrs=(color=white size=50cm);
     xaxis min=-3 max=3  display=none;
     yaxis min=-5 max=1  display=none;
  run;
  %end;
%mend;
%ANIMATION;

ods printer close ;
ods results;

options  ANIMATION=STOP ;


2016年7月19日火曜日

RWIで迷路を作る2



以下記事では、棒倒し法という方法を使って迷路を作りました。

RWIで迷路を作る
http://sas-boubi.blogspot.jp/2015/08/rwi.html


今回は穴掘り法という方法を使って迷路を描画してみます。
それと、もうちょっと見た目を迷路っぽく改良してみます。
(※ SAS9.4以降で動作します)



迷路作成の初期値を設定

%let n    = 37;
%let init = 1234;

n    ・・・ 迷路のマスの数。(必ず奇数を設定する事)
init  ・・・ 迷路の壁と床を決めるために生成する乱数のシード値

初期値を変えるたびに異なる迷路を作ることが出来ます。



迷路の生成と描画

ods noresults;
ods html path="★出力先のパスを指定" file="maze2.html";



*--- 穴掘り法による迷路の生成 ----------------------------------------------;
data _NULL_;


  * 乱数のシード ;
  call streaminit(&init);

  * 迷路のブロックを入れておく箱を用意 ;
  dcl hash hs(ordered:'yes');
  hs.definekey("x","y");
  hs.definedata("block");
  hs.definedone();

  * 始点候補のブロックを入れておく箱を用意 ;
  dcl hash st(ordered:'yes');
  st.definekey("no");
  st.definedata("x","y");
  st.definedone();


  * ブロックを作って箱に放り込む ;
  do y2=1 to &n;
      do x2=1 to &n;
   
         * 外側を道ブロック,それ以外壁ブロックを詰める(1:道ブロック 2:壁ブロック) ;
         if x2 in (1,&n) or y2 in (1,&n) then BLOCK=1;
         else BLOCK=2;

         * ブロックを放り込む ;
         hs.add(key:x2, key:y2, data:block);
       
         * 始点候補のブロックを放り込む ;
         if BLOCK=2 and mod(x2*y2,2)=1 then do;
            no+1;
            st.add(key:no, data:x2, data:y2);
         end;
      end;
  end;



  do i=1 by 1 while (1);

      * 始点候補更新 ;
      if i>1 then do;
          no=0;
          st.clear();
          do y2=1 to &n;
          do x2=1 to &n;
       
               * 始点候補のブロックを放り込む ;
               if x2^in (1,&n) and y2^in (1,&n) and mod(x2*y2,2)=1 then do;
                    hs.find(key:x2, key:y2);
                    if block=1 then do;
                        * 上下左右いずれか2マス先が壁ブロックだったら始点候補にする ;
                        block_num=0;
                        hs.find(key:x2-2, key:y2  ); block_num+(block=2);
                        hs.find(key:x2+2, key:y2  ); block_num+(block=2);
                        hs.find(key:x2,   key:y2-2); block_num+(block=2);
                        hs.find(key:x2,   key:y2+2); block_num+(block=2);
                        if block_num>0 then do;
                              no+1;
                              st.add(key:no,data:x2,data:y2);
                        end;
                    end;
               end;
       
          end;
          end;
      end;

      if st.num_items=0 then leave;


      * 始点をランダムに決めてブロックの位置を取得 ;
      no = ceil(rand('uniform') * st.num_items);
      st.find(key:no);
      x2=x; y2=y;

      * 進めなくなるまで道ブロックを詰めこんでいく ;
      do while (1);
   
          * 進めるか確認 ;
          block_num=0;
          hs.find(key:x2-2, key:y2  ); block_num+(block=2);
          hs.find(key:x2+2, key:y2  ); block_num+(block=2);
          hs.find(key:x2,   key:y2-2); block_num+(block=2);
          hs.find(key:x2,   key:y2+2); block_num+(block=2);
          if block_num=0 then leave;

          * 進行方向を決める ;
          RAND = ceil(rand('uniform')*4);


          * 進行方向の2マス先が壁なら掘る ;
          if RAND=1 then do; x_move=0;  y_move=-1; end;  * 上 ;
          if RAND=2 then do; x_move=0;  y_move=1;  end;  * 下 ;
          if RAND=3 then do; x_move=1;  y_move=0;  end;  * 右 ;
          if RAND=4 then do; x_move=-1; y_move=0;  end;  * 左 ;

          if i=1 then hs.replace(key:x2, key:y2, data:1) ;
          hs.find( key:x2+x_move*2 , key:y2+y_move*2);
          if block=1 then continue;

          hs.replace(key:x2+x_move  , key:y2+y_move  , data:1) ;
          hs.replace(key:x2+x_move*2, key:y2+y_move*2, data:1) ;

          * 2マス先に移動 ;
          x2=x2+x_move*2;
          y2=y2+y_move*2;

      end;
  end;



  * ブロックを箱から出して迷路組み立て(迷路の描画) ;
  length WID HEI $10.;
  dcl odsout ob();
  ob.table_start();

  do y=1 to &n;
      ob.row_start();

      do x=1 to &n;

         hs.find(key:x, key:y);
       
         wid="7mm";
         hei="7mm";
         if (x=2 and y=3) or (x=&n-1 and y=&n-2) then do;
            block=1;
         end;
         if mod(x,2)=0 then wid="1mm";
         if mod(y,2)=0 then hei="1mm";

         *** 壁と床を描画 ;
          if (x=3 and y=3) or (x=&n-2 and y=&n-2) then do;
             block=1;
          end;
          ob.format_cell(style_attr: " bordercolor="|| choosec(block,"white","black") ||
                                     " background=" || choosec(block,"white","black") ||
                                     " height="|| hei || " width=" || wid);
      end;

      ob.row_end();
  end;

  ob.table_end();

  stop;
run;


ods html close;
ods html;
ods results;



プログラム書いてる時は、楽しくていっきに書き上げたけど、長いですね。。

2015年12月24日木曜日

SASでクリスマスツリーを描いてみる



SGPLOTプロシジャで遊んでみました。

HTML出力が有効になっている前提です。
バージョンや環境によってうまく表示されないかも。。


*** ツリー描画用データ作成 ;
data TREE;
input X Y1-Y5;
cards;
0 1 0 -1 -2 -4
;
run;

*** ツリー描画 ;
title ;
proc sgplot data=TREE noautolegend;
   scatter x=X y=Y1 /  markerattrs=(symbol=starfilled size=0.8cm color=yellow);
   scatter x=X y=Y2 /  markerattrs=(symbol=trianglefilled size=1cm color=green);
   scatter x=X y=Y3 /  markerattrs=(symbol=trianglefilled size=2cm color=green);
   scatter x=X y=Y4 /  markerattrs=(symbol=trianglefilled size=3cm color=green);
   scatter x=X y=Y5 /  markerattrs=(symbol=squarefilled size=0.6cm color=brown);
   inset "Happy Holidays !!"/ position=bottom textattrs=(size=50cm);
   xaxis min=-3 max=3  display=none;
   yaxis min=-5 max=1  display=none;
run;




雪も降らせてみました。(SAS9.4以上で動作します)

*** ツリー描画用データ作成 ;
data TREE;
input X Y1-Y5;
cards;
0 1 0 -1 -2 -4
;
run;

*** ゆき描画用データ作成 ;
data SNOW;
  call streaminit(123);
  do X=-3 to 3 by 0.2;
     SNOW = rand('uniform')*8-4;
     output;
  end;
run;

data DT1;
  set TREE SNOW;
run;

*** ツリーとゆき描画 ;
title ;
proc sgplot data=DT1 noautolegend;
   styleattrs wallcolor=black;
   scatter x=X y=Y1 /  markerattrs=(symbol=starfilled size=0.8cm color=yellow);
   scatter x=X y=Y2 /  markerattrs=(symbol=trianglefilled size=1cm color=green);
   scatter x=X y=Y3 /  markerattrs=(symbol=trianglefilled size=2cm color=green);
   scatter x=X y=Y4 /  markerattrs=(symbol=trianglefilled size=3cm color=green);
   scatter x=X y=Y5 /  markerattrs=(symbol=squarefilled size=0.6cm color=brown);
   scatter x=X y=SNOW / markerattrs=(symbol=circlefilled size=0.1cm color=white);
   inset "Happy Holidays !!"/ position=bottom textattrs=(color=white size=50cm);
   xaxis min=-3 max=3  display=none;
   yaxis min=-5 max=1  display=none;
run;


単純な仕組みですが、散布図のシンボルを★▲■●にしてサイズを大きくして表示させています。


2015年9月15日火曜日

三角関数で星印を描画する


いろいろな関数を使ってみたかっただけの記事です。
やってることは三角関数つかって座標求めてSGPLOTで星を描画してるだけです。

*** 描画用データ作成 *********;
data DT1;
   * 星の中心のx軸とy軸の座標 ;
   x0 = 100;
   y0 = 100;

   * 星の中心からの半径 ;
   r  = 50;

   * 1辺の角度 ;
   degree = 360/5;

   * ラジアン変換用 ;
   rad = constant('pi')/180;

   * 星のかどの座標を取得 (90度からスタート) ;
   do i=0 to 10 by 2;
      x = x0 + cos((90+i*degree)*rad) * r;
      y = y0 + sin((90+i*degree)*rad) * r;
      output;
   end;
run;


*** 星描画 ******************;
proc sgplot data=DT1;
   series x=X y=Y;
   xaxis min=0 max=200;
   yaxis min=0 max=200;
run;


使用してる関数は以下の通り。

CONSTANT … 指定した数学定数を返す。 ('pi'で円周率を返す)
COS  … コサインを返す。 (角度をラジアン変換した数値を指定する)
SIN   … サインを返す。 (角度をラジアン変換した数値を指定する)



2015年8月2日日曜日

RWIで迷路を作る



RWIを使って迷路を描画してみます。
(※ SAS9.4以降で動作します)



迷路作成の初期値を設定

%let n    = 37;
%let init = 1234;

n    ・・・ 迷路のマスの数。(必ず奇数を設定する事)
init  ・・・ 迷路の壁と床を決めるために生成する乱数のシード値

初期値を変えるたびに異なる迷路を作ることが出来ます。


迷路の壁と床を乱数で決める

data DT1;

  *** 全マス目分の配列を定義 ;
  array AR(&n, &n) ;

  *** 最初から壁にする部分を2に設定 ;
  do y=1 to &n;
      do x=1 to &n;
         if x in (1,&n) or y in (1,&n) or mod(x*y,2)=1 then AR(x,y)=2;
         else AR(x,y)=1;
      end;
  end;

  *** 乱数を生成して壁の位置を決める ;
  *** 壁の位置 1:上、2:下、3:右、4:左 ;
  call streaminit(&init);
  do y=3 to &n-2 by 2;
  do x=3 to &n-2 by 2;

     *** 1段目は上下左右の壁の乱数を生成 ;
     if y=3 then do;
         * 左のマスが壁だったら上下右のみの壁の乱数を生成 ;
         if AR(x-1,y)=2 then  RAND = ceil(rand('uniform')*3);
         else RAND = ceil(rand('uniform')*4);
     end;

     *** 2段目以降は下左右の壁の乱数を生成 ;
     if y^=3 then do;
         * 左のマスが壁だったら下右のみの壁の乱数を生成 ;
         if AR(x-1,y)=2 then  RAND = ceil(rand('uniform')*2)+1;
         else RAND = ceil(rand('uniform')*3)+1;
     end;

     if RAND=1 then AR(x,y-1)=2; * 上 ;
     if RAND=2 then AR(x,y+1)=2; * 下 ;
     if RAND=3 then AR(x+1,y)=2; * 右 ;
     if RAND=4 then AR(x-1,y)=2; * 左 ;
  end;
  end;
run;


RWIで迷路描画

data _NULL_;
  length VAR1 $5.;
  set DT1;
  array AR(&n, &n);
  dcl odsout ob();
  ob.table_start();

  do y=1 to &n;
      ob.row_start();

      do x=1 to &n;

         *** 壁と床を描画 ;
          VAR1="";
          if (x=2 and y=2) or (x=&n-1 and y=&n-1) then VAR1="☆";
          ob.format_cell(data:VAR1,  style_attr: "background=" || choosec(AR(x,y),"white","black") ||
                                                                  " height=0.4cm  width=0.4cm");
      end;

      ob.row_end();
  end;

  ob.table_end();
run;


2015年5月12日火曜日

RWIでフォトブックをつくる



※ SAS9.4以降で動作します。
また、貼り付ける画像ファイルによっては、出来上がるファイル容量も馬鹿でかくなるので、PCの空き領域がない場合は、実行しない方がいいかも。


プログラムを実行する場合は、プログラム中の青字にしてるパスを各時環境のパスに変更してください。

プログラムで使う写真

   



プログラム
ods html close;
ods pdf file="出力するファイルのパス\photobook.pdf" notoc  dpi=150;

data _NULL_;
  dcl odsout ob();

  *** 1ページ目 ***************************;
  ob.layout_absolute();

    * 1枚目の写真 ;
    ob.region( x:'2cm',  y:'1cm',  width:'9cm' );
    ob.image( file:'写真を格納したパス\DSC_0614.JPG' );

    ob.region( x:'12cm',  y:'5cm',  width:'7cm' );
    ob.format_text( data:"夏の恒例「SASユーザー総会」",
                         style_attr:"fontsize=12pt" );

    * 2枚目の写真 ;  
    ob.region( x:'10cm',  y:'12cm',  width:'8cm');
    ob.image( file:'写真を格納したパス\DSC_0618.JPG' );

    ob.region( x:'2cm', y:'22cm', width:'8cm' );
    ob.format_text( data:"ユーザー総会限定の粗品",
                         style_attr:"fontsize=12pt" );
    
  ob.layout_end();

  ob.page();

  *** 2ページ目 ***************************;
  ob.layout_absolute();

    * 1枚目の写真 ;
    ob.region( x:'2cm', y:'1cm', width:'10cm' );
    ob.image( file:'写真を格納したパス\DSC_0489.JPG' );

    ob.region( x:'12.5cm', y:'5cm', width:'7cm' );
    ob.format_text( data:"堀切菖蒲園の菖蒲たち",
                         style_attr:"fontsize=12pt" );

    * 2枚目の写真 ;  
    ob.region( x:'2cm', y:'9cm', width:'10cm' );
    ob.image( file:'写真を格納したパス\DSC_0611.JPG' );

    ob.region( x:'12.5cm', y:'16cm', width:'7cm' );
    ob.format_text( data:"熱い将棋バトル、電王戦タッグマッチ2014",
                         style_attr:"fontsize=12pt" );
 
  ob.layout_end();

run;

ods pdf close;
ods html;


結果





写真の解像度が高いと、出来上がるPDFファイルの容量も大きくなってしまいます。

プログラム2行目の「ods pdf  ~ dpi=150;」で、解像度を設定してます。
デフォルトは 「dpi=150」なので、写真枚数が多い場合は、ファイル容量が恐ろしくやばくなるので、まずは「dpi=75」とかにして、様子を見たほうがいいかも。


今回使用してるRWIについては、以下の入門シリーズにまとめています。
レポート作成インターフェイス(RWI)入門1

2015年1月5日月曜日

1年分のカレンダーを作るSASプログラム



本年も、どうぞよろしくお願い致します!!


年の始まりということで、以前紹介した「RWIでカレンダーを作ってみる。」を改良して、1年分のカレンダーを作るプログラムを2パターン作りました。
祝日を色分けする処理も加えてます。


ちなみにSAS9.4以降で動作します。
また、実行する場合は、最後のほうに書いた補足の通り、プログラムを直してください。


(2020/12/26 出力結果のタイトル文字を大きくするなど、プログラムを改良)


まずは、以下の通り、その年の祝日をデータセット化しておきます。
「祝日一覧」とか適当にググると調べられます。

*** 2015年の祝日をデータセット化 ;
data HOLIDAY;
input  i :yymmdd10. HOLIDAY :$30.;
cards;
2015/1/1 元日
2015/1/12 成人の日
2015/2/11 建国記念の日
2015/3/21 春分の日
2015/4/29 昭和の日
2015/5/3 憲法記念日
2015/5/4 みどりの日
2015/5/5 こどもの日
2015/5/6 振替休日
2015/7/20 海の日
2015/9/21 敬老の日
2015/9/22 国民の休日
2015/9/23 秋分の日
2015/10/12 体育の日
2015/11/3 文化の日
2015/11/23 勤労感謝の日
2015/12/23 天皇誕生日
;


カレンダーのパターン①



*** 年を指定 ;
%let YEAR = 2015;


*** 用紙の向きを横に ;
options orientation = landscape;


title height=20pt "SAS Calendar ( &YEAR )";
ods pdf file="出力するパス\calendar1.pdf" notoc;


*** RWIでカレンダーを作る ;
data _NULL_;

  * 祝日一覧をハッシュオブジェクトに格納 ;
  length HOLIDAY $20.;
  dcl hash hs( dataset:"HOLIDAY" );
  hs.definekey( "i" );
  hs.definedata( "HOLIDAY" );
  hs.definedone();


  * 月ごとにループ ;
  do MONTH = 1 to 12;

     * 月の開始日と終了日を取得 ;
     STDT = mdy(MONTH, 1, &YEAR);
     ENDT = intnx("month", STDT, 0, "end");

     * カレンダー作成開始 ;
     dcl odsout ob();
     ob.table_start();

         * 月を出力 ;
         ob.head_start();
         ob.row_start();

              ob.format_cell( data: put(STDT,monname20.), column_span:7,
                                     style_attr: "background=midnightblue  color=white
                                                      fontsize=10  fontweight=bold  just=left");
         ob.row_end();

         * 曜日を出力 ;
         ob.row_start();
              do i = 1 to 7;
                  ob.format_cell( data: char("SMTWTFS",i) ,
                                        style_attr: "background=skyblue color=white fontsize=5") ;
              end;
         ob.row_end();
         ob.head_end();

         * 日付を出力 ;
         ob.row_start();
              do i = STDT to ENDT;

                  * 初日が日曜以外であれば空白を埋める ;
                  if i=STDT then do i2=1 to weekday(STDT)-1;
                      ob.format_cell();
                  end;

                  * 日付を出力 (文字色も設定) ;
                  HOLIDAY="";

                  *--- 平日は黒 ;
                  COLOR="BLACK";

                  *--- 日曜と祝日は赤 ;
                  if weekday( i )=1 or hs.find()=0 then COLOR="RED";

                  *--- 土曜は青 ;
                  else if weekday( i )=7 then COLOR="BLUE";

                  ob.format_cell( data:cats( day( i ), "#", HOLIDAY ) ,split:"#",
                                         style_attr:"height=2.7cm width=3.5cm fontsize=5 color="||COLOR);


                  * 土曜日であれば折り返す ;
                  if weekday( i )=7 and i^=ENDT then do;
                       ob.row_end();
                       ob.row_start();
                  end;

              end;
         ob.row_end();

      ob.table_end();

      * 月ごとに改ページ ;
      if MONTH^=12 then ob.page();

  end;
run;


ods pdf close;




カレンダーのパターン②




*** 年を指定 ;
%let YEAR = 2015;


*** 用紙の向きを縦に ;
options orientation = portrait;


title height=20pt "SAS Calendar ( &YEAR )";
ods pdf file="出力するパス\calendar2.pdf" notoc;


*** RWIでカレンダーを作る ;
data _NULL_;

  * 祝日一覧をハッシュオブジェクトに格納 ;
  length HOLIDAY $20.;
  dcl hash hs( dataset:"HOLIDAY" );
  hs.definekey( "i" );
  hs.definedata( "HOLIDAY" );
  hs.definedone();

  * カレンダー作成開始 ;
  dcl odsout ob();
  ob.layout_gridded(columns:3,rows:4);

  * 月ごとにループ ;
  do MONTH = 1 to 12;

      * 月の開始日と終了日を取得 ;
      STDT = mdy(MONTH, 1, &YEAR);
      ENDT = intnx("month", STDT, 0, "end");

      ob.region();
      ob.table_start();

         * 月を出力 ;
         ob.head_start();
         ob.row_start();

              ob.format_cell( data: put(STDT,monname3.), column_span:7,
                                     style_attr:"background=midnightblue  color=white 
                                                     fontsize=3  fontweight=bold  just=left");
         ob.row_end();

         * 曜日を出力 ;
         ob.row_start();
              do i = 1 to 7;
                  ob.format_cell( data: char("SMTWTFS",i),
                                        style_attr: "background=lightsteelblue color=white");
              end;
         ob.row_end();
         ob.head_end();

         * 日付を出力 ;
         ob.row_start();
              do i = STDT to ENDT;

                  * 初日が日曜以外であれば空白を埋める ;
                  if i=STDT then do i2=1 to weekday(STDT)-1;
                      ob.format_cell();
                  end;


                  * 日付を出力 (文字色も設定) ;
                  HOLIDAY="";

                  *--- 平日は黒 ;
                  COLOR="BLACK";

                  *--- 日曜と祝日は赤 ;
                  if weekday( i )=1 or hs.find()=0 then COLOR="RED";

                  *--- 土曜は青 ;
                  else if weekday( i )=7 then COLOR="BLUE";

                  ob.format_cell( data: day( i ), style_attr:"color="||COLOR );


                  * 土曜日であれば折り返す ;
                  if weekday( i )=7 and i^=ENDT then do;
                       ob.row_end();
                       ob.row_start();
                  end;

             end;
         ob.row_end();
      ob.table_end();

  end;
  ob.layout_end();
run;


ods pdf close;




補足


・プログラムの最初らへんの「ods pdf」部分を、各自保存したいパスに変えてください。
ods pdf file="結果を保存するパス\ファイル名.pdf";


・ 出力する年を変えたい場合は、プログラム先頭の以下の箇所を変えてあげる。

*** 年月を指定 ;
%let YEAR = 2015;

また、その年の祝日にあわせてデータセットHOLIDAYを更新してください。



2014年12月26日金曜日

今年も1年有難うございました&締めのPROC EXPLODE


今年もあとちょっとですね。
ブログを見てくださった方や、コメントくださった方、皆さん本当に有難うございました!

まだ今年も更新するかもしれませんが、来年もよろしくお願いします!

とりあえず、一度使ってみたかったEXPLODEプロシジャで締めたいと思います。

filename ft15f001 temp;

proc explode;
parmcards;
1 HAVE A GREAT
2 NEW YEAR!!
;
run;


。。。SAS Studioだと、結果がでないので、
ログ・アウトプットを外部ファイルに出力する。で紹介したPRINTTOプロシジャで、出力結果をテキストファイルとして保存し、SAS Studio上でそのテキストファイルを開くと、見れると思います。

2014年11月6日木曜日

RWIでカレンダーを作ってみる。



遊び回です。RWIでカレンダー作ってみました。

style_attrで細かい書式設定をしてるため、ごちゃごちゃして見えますが、そこを見なければプログラムとしてはシンプルな構造になってます。


※ SAS9.4以降で動作します。

*** 年月を指定 ;
%let YEAR = 2014;
%let MONTH = 11;


*** RWIでカレンダーを作る ;
data _NULL_;

  * 月の開始日と終了日を取得 ;
  STDT = mdy(&MONTH, 1, &YEAR);
  ENDT = intnx("month", STDT, 0, "end");

  * カレンダー作成開始 ;
  dcl odsout ob();
  ob.table_start();

     * 月を出力 ;
     ob.head_start();
     ob.row_start();
          ob.format_cell( data: put(STDT,monname20.), column_span:7,
                                 style_attr: "background=midnightblue  color=white
                                                  fontsize=10  fontweight=bold  just=left");
     ob.row_end();

     * 曜日を出力 ;
     ob.row_start();
          do i = 1 to 7;
              ob.format_cell( data: char("SMTWTFS",i) ,
                                    style_attr: "background=skyblue color=white fontsize=5") ;
          end;
     ob.row_end();
     ob.head_end();

      * 日付を出力 ;
     ob.row_start();
          do i = STDT to ENDT;

              * 1日が日曜以外であれば空白を埋める ;
              if i=STDT then do i2=1 to weekday(STDT)-1;
                  ob.format_cell();
              end;

              * 日付を出力 ;
              ob.format_cell( data:day( i ) ,  style_attr:"height=2cm width=2cm fontsize=5;");

              * 土曜日であれば折り返す ;
              if weekday( i )=7 and i^=ENDT then do;
                   ob.row_end();
                   ob.row_start();
              end;

          end;
     ob.row_end();

  ob.table_end();
run;

結果




補足

・大体以下で紹介した事をもとにしてます。
レポート作成インターフェイス(RWI)入門1
レポート作成インターフェイス(RWI)入門2
レポート作成インターフェイス(RWI)入門3


・出力する年月を変えたい場合は、プログラム先頭の以下の箇所を変えてください。

*** 年月を指定 ;
%let YEAR = 2014;
%let MONTH = 11;


・PDFなどに出力して印刷したい場合は、プログラムの先頭と最後に以下の文を挿入すればok。
 先頭: ods pdf file="結果を保存するパスを指定\SAS_Calendar.pdf";
 最後: ods pdf close;