2020年2月6日木曜日

グラフのマーカーや線などの属性をGROUP毎に設定する【Attribute Map Statement 編】



「Attribute Map Statement」を利用して、GTLでマーカーや線などの属性を定義する方法を紹介。



と、その前に、以前「Attribute Map Dataset」を紹介しました。
グラフのマーカーや線などの属性をGROUP毎に設定する【Attribute Map Dataset 編】


今回はもう1つの方法として「Attribute Map Statement」を紹介していきます。
(※Attribute Map StatementはGTLのみの機能となります)



さっそくサンプルプログラム

proc template ;
     define statgraph MYTEMP ;
     begingraph;

     /* Attribute Map を定義 */
     discreteattrmap name="mymap";
        value "11" "12" / markerattrs=(color=blue    symbol=starFilled        size=11);
        value "13" "14" / markerattrs=(color=yellow symbol=TriangleFilled  size=11);
        value other       / markerattrs=(color=red      symbol=CircleFilled     size=11);
     enddiscreteattrmap;

     /* 「Attribute Map」と「グループ変数」を関連付ける */
     discreteattrvar  var=age attrmap="mymap" attrvar=myvar;

     /* 「Attribute 変数」の使用 */
     layout overlay;
          scatterplot x=HEIGHT y=WEIGHT / group=myvar grouporder=ascending name="leg1";
          discretelegend "leg1" / title="Age";
     endlayout;

     endgraph;
     end;
run;

proc sgrender data=SASHELP.CLASS template=MYTEMP;
run;


上の例では以下のような設定をしています。
  • 年齢(AGE)をグループ変数として、マーカーの種類と色を以下に設定
  • AGEが「11」「12」の時、青色の星マーク
  • AGEが「13」「14」の時、黄色の三角マーク
  • AGEが上記以外の時、赤色の丸マーク


ではどのように設定しているか見ていきましょう。




Step1. 「Attribute Map」を定義する


まずは、グループ変数の値にどういった書式(属性)を割り当てるのか?を定義します。

構文
DISCRETEATTRMAP  NAME="Attribute Mapの名前";
     VALUE  "グループ変数の値1"  /  属性;
     VALUE  "グループ変数の値2"  /  属性;
     …
ENDDISCRETEATTRMAP;


今回は以下のように書いています。

discreteattrmap name="mymap";
   value "11" "12" / markerattrs=(color=blue    symbol=starFilled        size=11);
   value "13" "14" / markerattrs=(color=yellow symbol=TriangleFilled  size=11);
   value other       / markerattrs=(color=red      symbol=CircleFilled     size=11);
enddiscreteattrmap;

  • 「mymap」というAttribute Map を定義
  • グループ変数の値が「11」「12」の時、青色の星マーク
  • グループ変数の値が「13」「14」の時、黄色の三角マーク
  • グループ変数の値が上記以外の時、赤色の丸マーク


ちなみに属性には「マーカー」や「塗りつぶし」といった設定を行う以下の属性オプションが用意されています(GTL書いたことある人ならお馴染みの書き方)

  • MARKERATTRS=()
  • FILLATTRS=()
  • LINEATTRS=()
  • TEXTATTRS=()


重要ポイント

グループにする変数にFORMATが割り当てられている場合、FORMATを当てた後の値を指定する事。
例えば年齢をグループ変数とする場合、11 = "11歳" のようにFORMATが当てられている場合、"11歳" の方を指定する。

discreteattrmap name="mymap";
   value "11歳"  / markerattrs=(color=blue symbol=starFilled  size=11);
enddiscreteattrmap;




Step2. 「Attribute Map」と「グループ変数」を関連付ける


次に、先ほど定義した「Attribute Map」と「実際のグループ変数」を関連付けます。


構文
DISCRETEATTRVAR
    VAR              = グループ変数
    ATTRVMAP  = "グループ変数と関連付けるAttribute Map"
    ATTRVAR     = グループ変数とAttribute Mapの関連付けに対して、任意の名前を定義
;


今回は以下のように書いています。

discreteattrvar var=age attrmap="mymap" attrvar=myvar ;

「グループ変数=AGE」と「Attribute Map="mymap"」を「myvar」という名前(Attribute変数)で関連付けています。



Step3. 「Attribute変数」の利用


あとはPLOTするときに、グループ変数として「Attribute変数」を指定すればOK

scatterplot x=HEIGHT y=WEIGHT / group=myvar grouporder=ascending ;

これで、Attribute Mapの定義に基づいてマーカーの種類や色などの属性を展開してPLOTしてくれます。

注意:
SAS9.4M3より前のバージョンでは、この機能 (Attribute Map Statement) と一緒に、PLOTステートメント (SCATTERPLOTやSERIESPLOTなど) でも属性を定義している場合、結果のプロット部分と凡例部分の属性が一致していないおかしな状態になってしまうことがある?らしいので注意。



2020年1月28日火曜日

[CALL SORT] 1オブザベーション内で変数間の値をソートする





SAS9.4M6で「CALL SORT」が追加されてますね。
これは「1オブザベーション内で変数間の値をソート」することができます。


例1
data test;
    x=2; y=3; z=1;
run;






data test2;
    set test;
    call sort(x,y,z);
run;


数値変数 X, Y, Z に対して、1つのオブザベーション内で値を昇順にソートしています。



例2
data test3;
    length x y z $3.;
    x="tea"; y="sas"; z="";
run;






data test4;
    set test3;
    call sort(x,y,z);
run;





文字変数 X, Y, Z に対して、1つのオブザベーション内で値を昇順にソートしています。




ポイント
  • 引数がすべて数値変数の場合は数値としてソートし、引数がすべて文字変数の場合は文字としてのソートが行われます
  • 引数に指定する変数の LENGTH はすべて同じであること


上のポイントの1つ目についてもっと詳しくいうと、たとえば、以下のように文字変数に数値が格納されている場合、

data test5;
    length x y z $3.;
    x = "2";
    y = "1";
    z = "10";
run;


それを CALL SORT(X,Y,Z) とすると、文字変数なんで文字としてのソートが行われて、

x = "1";
y = "10";
z = "2";

となります。


2020年1月20日月曜日

SVGにコントロールボタンを仕込む [SVGCONTROLBUTTONS, SVGMAGNIFYBUTTON]





システムオプション「SVGCONTROLBUTTONS」と「SVGMAGNIFYBUTTON」を指定して、SVGファイルにちょっとした仕掛けを組み込むことが出来ます。


サンプルプログラム
options svgcontrolbuttons svgmagnifybutton;

ods _all_ close;
ods printer printer=svg file="出力するパス/test.svg";

title "棒グラフ";
proc sgplot data=sashelp.class;
    vbar age / response=height group=Sex groupdisplay=cluster stat=mean fillpattern;
run;

title "散布図";
proc sgplot data=sashelp.class;
    scatter x=height y=weight;
run;

ods printer close;
ods html;



以下が作成されたSVGファイルです。


上の方にボタンが出てきました。



システムオプション「SVGMAGNIFYBUTTON」で拡大ボタンが追加されます。
ボタンを押すと、マウスカーソルの位置が拡大されて表示されます。




システムオプション「SVGCONTROLBUTTONS」でインデックスボタンが追加されます。ページの一覧が表示され、サムネイルをクリックするとそのページが開きます。



「前へ」とか「次へ」のボタンを押してページ移動させることが出来ます。




グラフを沢山つくって、眺めたいときにこの機能が便利そうね。



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;




2019年12月14日土曜日

[KCHARLIST関数] 「アルファベット」や「数字」などの特定の文字列を返す





SAS9.4M5から追加になった「KCHARLIST関数」がいい感じです。


例1

data test;
   length x $500.;
   x = kcharlist("U");
run;



KCHARLIST関数で指定した「"U"」は「大文字のアルファベット」を意味しています。
ご覧の通り、戻り値として大文字のアルファベットが返されました。



このように特定の種類の文字をリストとして取得することができます。
「"U"」の他に以下なども指定可能です(一部抜粋)

  • "A"  =  大文字と小文字のアルファベット
  • "L"  =  小文字のアルファベット
  • "U"  =  大文字のアルファベット
  • ”D”  =  数字
  • ”F”  =  SAS名(変数名やデータセット名など)で有効な開始文字
...などなど



2019年12月6日金曜日

[SGプロシジャ] スタイル属性の組み合わせ方法を設定する





SAS9.4で追加になった「ODS GRAPHICS の ATTRPRIORITY=オプション」をご紹介します。


この「ATTRPRIORITY=オプション」は、SGプロシジャでの「スタイル属性の組み合わせ方法」を設定することができます。
ていわれても意味不明かもしれないんで、とりあえず例を見てみましょうか。





「ATTRPRIORITY=オプション」の例


ATTRPRIORITY=COLOR

ods graphics / attrpriority=color;

proc sgplot data=sashelp.class;
    styleattrs datacontrastcolors=(blue orangedatasymbols=(circlefilled starfilled) ;
    scatter x=height y=weight / group=sex markerattrs=(size=12pt);
run;




  • 変数SEXをグループ変数として、シンボルを分けています。
  • 今回は説明しやすくするため、STYLEATTRSステートメントを使って、以下のスタイル属性を明示的に設定しています。
    • シンボルカラーを「BLUE」と「ORANGE」
    • シンボルを「円」と「星」


このスタイル属性に対して「ATTRPRIORITY=COLOR」は以下のイメージでグループごとの「スタイル属性の組み合わせ」を作ります。













1つ目のグループ「BLUE」と「円」の組み合わせ
2つ目のグループ「ORANGE」と「円」の組み合わせ
3つ目のグループ「BLUE」と「星」の組み合わせ
4つ目のグループ「ORANGE」と「星」の組み合わせ

というようにカラーを循環させて組み合わせていきます。





ATTRPRIORITY=NONE

ods graphics / attrpriority=none;

proc sgplot data=sashelp.class;
    styleattrs datacontrastcolors=(blue orangedatasymbols=(circlefilled starfilled) ;
    scatter x=height y=weight / group=sex markerattrs=(size=12pt);
run;



「ATTRPRIORITY=NONE」は以下のようなイメージです。



1つ目のグループ「BLUE」と「円」の組み合わせ
2つ目のグループ「ORANGE」と「星」の組み合わせ

というようにすべてのスタイル属性をグループごとに循環させていきます。





長所と短所



  • 「ATTRPRIORITY=NONE」とした方が見やすいグラフになりやすい

さきほどの「ATTRPRIORITY=COLOR」の例では、グループごとに「色違いの同じシンボル(円)」がPLOTされているのに対して、「ATTRPRIORITY=NONE」の例では、グループごとに「色もシンボルも異なる」PLOTができるので、当然見やすくなるわけです。



  • 「ATTRPRIORITY=COLOR」の方が、組み合わせを多く作れる

記事の最初に示した例では、2つの「シンボル」と2つの「色」をスタイル属性として定義しました。
これに対して「ATTRPRIORITY=COLOR」では4つの組み合わせが作れるのに対して、「ATTRPRIORITY=NONE」では2つしか作れません。


なにが言いたいかというと、たとえば以下の例をご覧ください。

ods graphics / attrpriority=none;

proc sgplot data=sashelp.class;
    styleattrs datasymbols=(circlefilled starfilled) datacontrastcolors=(blue orange);
    scatter x=height y=weight / group=age markerattrs=(size=12pt);
run;



変数AGEをグループ変数として、シンボルを分けていますが、異なるグループにも関わらず、同じシンボルとカラーが割り当てられてしまいました。


これは、スタイル属性が循環して使われるためです。
(たとえばカラー属性だと「BLUE」→「ORANGE」→「BLUE」→「ORANGE」という感じで、設定されている色を使い切ると循環して同じ色が使われる)

この循環は「ATTRPRIORITY=COLOR / NONE」どちらも起こり得ますが、使える組み合わせが少ないと、こういった不具合を起こしていしまいやすいですね。


2019年11月28日木曜日

[SGPLOT] BY値ごとにグラフを作成する際、軸やシンボルなどをグラフ間で揃えたい






これは SGPLOT をよく使用する方なら一度は困るところではないでしょうか?
まずは、以下の失敗例をご覧ください。



失敗例

/* Sample Data */
proc sort data=sashelp.class (obs=5) out=class;
    by age;
run;

/* BY値ごとにグラフを作成 */
ods graphics / height=400 width=400;

proc sgplot data=class;
    scatter x=height y=weight / group=sex markerattrs=(symbol=circlefilled);
    by age;
run;




「BYステートメント」によって、変数「AGE」の値ごとにグラフを作成しています。
また「GROUP=オプション」によって、変数「SEX」の値ごとにシンボルカラーを変えています。



ここで気になるのが、、

  • X軸とY軸の目盛がグラフ間で異なっている。
  • シンボルの色がグラフ間で異なっている(SEX=Fのシンボルが、AGE=13の時は青、AGE=14の時は赤になっている)



そうなんですよ、、BY値ごとにグラフを作成すると、軸やシンボルはグラフ間で統一してくれません。
でも解決方法は簡単!



成功例

proc sgplot data=class uniform=all;
    scatter x=height y=weight / group=sex markerattrs=(symbol=circlefilled);
    by age;
run;




UNIFORM=オプション」を指定するだけ!
このオプションは「BY値ごとに作成したグラフのどこを統一させたいか」を設定します。
設定値には以下があります。



UNIFORM=

 設定値 設定内容 
SCALEX軸を統一 and Y軸を統一
XSCALEX軸を統一
YSCALEY軸を統一
GROUP「GROUP=オプションに指定した変数の値ごとにシンボルや線種などを統一
XSCALEGROUP「XSCALE」と「GROUP」の両方を設定
YSCALEGROUP「YSCALE」と「GROUP」の両方を設定
ALL上記のすべてを統一