通常のMergeとDS2のMergeは別物という話

当初DS2プロシジャがリリースされた時,なんと文法からMergeステートメントが廃されてました.データの結合は,内部埋め込みできるFedSQLやHash Packageでも使いなさいという思い切った仕様でした

個人的には,左側外部結合の多い医薬分野の自分のプログラムの範囲では,SASにMergeステートメントは必要ない,基本ハッシュオブジェクトがあればいい,SQLの方が性にあるというならjoinする人がいても良いという過激思想なので(人に押し付けるつもりはないですが…笑)

当時は思い切ったことをしたものだと感心しました.
まあ,DS2の場合,基本的に内部処理のベースがSQLで行われているようで,byの挙動などもSQLのorder by,group byに準じていたりするので,SAS固有の特殊な挙動をするMergeステートメントを親和させれたなったんだろうなぁと推察してました

ただ,やはりちょっと思い切り過ぎたのでしょうかね,メンテナンスリリース3あたりで,突如DS2にもMergeが搭載されました.旧来のユーザーからの要望?

ただ,やっぱり,本来仕組みの違うものに,組み込んだので,ちょっと注意が必要です.
まあ,基本的なケースでは同じ結果が返るので,使わない方がとまでは言わないのですが,知った上で気を付けて使ってくださいって話です

data T1;

length K 8. A B $20.;

K=101;A="Cat";B="Apple";output;

K=101;A="Pig";B="Banana";output;

K=102;A="Duck";B="Fig";output;

run;




data T2;

length K 8. A C $20.;

K=101;A="Cow";C="Red";output;

K=102;A="";C="Yellow";output;

K=103;A="";C="Blue";output;

run;


旧来のデータステップのMergeであれば

data A1;

merge T1 T2;

by K;

run;


後続のデータが,先行の共通で変数バッティングするところを上書いていく,いかにもSASのマージっぽい結果ですね


一方,DS2のmergeはというと


proc DS2;

data A2 (overwrite=yes);

   method run();

      merge T1 T2;

      by K;

   end;

enddata;

run;

quit;

(ライブラリやSODの出力ビューが自動更新されないので,製品SASの場合はライブラリを切り替えて戻ってきて見るか,SODならライブラリ開いて確認できます)


ほぼ同じと見せかけて,Cの2行目が欠損なことに注目です.
T2に101のデータが1つしかないからこうなってます

SASの場合はkey一致分,全てに値がつくのですが,見方を変えると同key 前obsから値がretainされているとも解釈できます

そして,DS2のM5でMergeにretainオプションが追加され,これを使うと

proc DS2;

data A3 (overwrite=yes);

   method run();

      merge T1 T2 / retain;

      by K;

   end;

enddata;

run;

quit;








おっ,今度はCの2行目に値がはいった!
しかし実はよく見ると,これも旧来のデータステップの結果と違うのです
Aの2行目,1行目の値がそのままretainされています

というわけで,今までのmergeと同じ出力結果をだすのは中々に難しいのですね
挑戦してみると面白いかもですが,SQLで今回のデータステップのmergeと同じ結果だすの結構難しいはず

ただ,まあそれぞれの結果のどれが正しいという話ではないのですね.旧来の結果に見慣れてるので,DS2のマージはおかしいって言いたくなるのですが,それもあくまで仕様どおりにでてるだけということですね

RMSTのグラフを描いてみた話

とても反抗的で手の付けられない後輩が,SASユーザー総会でRMSTの発表をしてました.
RMSTオプションは良いなぁと思うのですが,ods gprahicsででてくるKM plotは特にいつも通りのものしかでません

Pythonのlifelinesライブラリとかだと割と簡単で

from matplotlib import pyplot as plt

from lifelines.utils import restricted_mean_survival_time

from lifelines.plotting import rmst_plot

bmt=impsas(folder,"bmt")

ix=bmt['Group']=='ALL'

T, E = bmt['T'], bmt['Status']

time_limit = 1500

kmf_exp = KaplanMeierFitter().fit(T[ix], E[ix], label='exp')

rmst_plot(kmf_exp, t=time_limit)


それっぽいものがでて,視覚的にもわかりやすいのですが,これをSASでやるのは面倒です

すでにSASoneさんの方で作図例があるのですが
http://sasonediver.blog.fc2.com/blog-entry-253.html 

annotation使わずに,描けないかなぁと思いました

Number at Risk表つくってる場合,通常,境界時間τは,そんな中途半端な時点にならずにat Riskだしてるポイントと被ることが多いので
それなら,信頼区間バンドつけるときの下限を0にしちゃえばいいんじゃねってことで

%let tau=1500;


ods output Survivalplot=SurvivalPlotData;

ods output RMST=RMST(rename=(Stratum=StratumNum));

proc lifetest data=sashelp.bmt  rmst(tau=&tau) plots=survival(atrisk=0 to 2500 by 500 );

    time T*STATUS(0);

    strata group;

run; 

data SurvivalPlotData_1;

  set SurvivalPlotData;

  if 0 then set RMST;

  if _N_=1 then do;

    declare hash h1(dataset:"RMST");

    h1.definekey("StratumNum");

    h1.definedata("Estimate");

    h1.definedone();

  end;

  retain _Survival;

  if ^missing(Survival) then _Survival=Survival;

  markerchar=" ";

  if ^missing(Censored) then hige=Censored+0.03;

  if time<=&tau then limit_time=time;

  h1.find();

  if tAtRisk eq &tau then do;

    tau=&tau;

    rmst=cats("RMST=",round(Estimate,0.1));

    ry=_Survival -0.05;

  end;

run;


proc sgplot data=SurvivalPlotData_1 noautolegend;

styleattrs datacontrastcolors=(black black black) datacolors =(blue yellow red);

  step x=time y=survival /CURVELABEL group=stratum lineattrs=(thickness=3);

  scatter x=time y=censored /NOERRORCAPS yerrorupper=hige errorbarattrs=(pattern=1 thickness=3)  markerchar=markerchar GROUP=stratum;

  band  x=limit_time upper=_survival lower=0/ group=stratum type=step transparency=0.7;

  text x=tau y=ry text=rmst/textattrs=(size=15);

  xaxistable atrisk / x=tatrisk class=stratum location=outside colorgroup=stratum valueattrs=(size=10);

  refline tau/axis=x;

  yaxis label="Survival Probability" min=0 offsetmax=0.1;

  xaxis label="Day" min=0 offsetmin=0.01 ;

run;



おー,なんかそれっぽい


dosubl関数でviewを設定して同ステップでそのままハッシュオブジェクトのソースにする話

そろそろ,いいかなぁって.
アメリカの某SASの集まりで発表して賞取ったネタ.
通常hashのdataset:で指定するものは,データステップ開始時点で存在しているデータセット(ビュー)でなければいけないが,dusubl関数でのコード実行のみ,ステップ開始後の生成で間に合ってしまうという話.
マクロ化すれば,様々なサブセットや,SQLクエリの抽出結果からそのままデータ取得をいくらでもやり放題という技術.
結構,劇的に開発効率をあげれる(少なくとも私自身は)技術で重宝している

data output;

set sashelp.class;

if _N_ = 1 then do;

rc=dosubl("proc sql noprint;

                create view v1 as

                select sex ,mean(age) as age_mean

                from sashelp.class

                group by sex;

                quit;");

drop rc;

declare hash h1(dataset:"v1");

h1.definekey("sex");

h1.definedata("age_mean");

h1.definedone();

end;

if h1.find() ne 0 then call missing(age_mean);

run;



 

そっかselectで初期化されてない変数うつとそういう結果になるんだったなって話

data a;

   select (X) ;

     when ("A") out ="AAAAA" ;

     when ("B") out ="BBBBB" ;

     otherwise;

   end ;

run;












そっか,怖いですね,これ.いまさらながらに,はっとしました(笑)

SASのクソな部分をぶった切る! をぶった切らない話

 最近,色んな方が凄いレベルの高いブログ更新されてて,すっかり楽しく拝見する側にまわってます.

個人的に尖った人が好きなのですが,

最近,よく「SASのクソな部分をぶった切るシリーズ」について,どう思うんですか?って色んな方から訊かれるのです.普通に面白いって答えてます(笑)

でも,自分の好きなSASがけなされてる?ということで,なんか良くない気持ちになってる人も一定いたり,急に新人がSAS勉強しなくなって困っちゃった人もいるようなので,一応私が思うことだけ

SASのクソな部分をぶった切る!(1) ソフトウェア価格

https://superman-jp.hatenablog.com/entry/SAS-disadvantage-1

>うん,これはわりとその通りかも(笑)いいぞ もっとやれ.

まあ,医薬分野ってSASの売り上げの20%ぐらいだっけ?で,さらにLSAFとかではなくて,ゴリゴリSAS BASE書いてるユーザーはSASからみたら,金額的にそんなに重視する部分じゃないので,多分,眼中にないのでしょう.払うやつ,払えれる民草が払えばいいと(笑)

私もOpen Source Technologyを申請資料作成にみたいなことに絡んでたりするので,確かな流れとして脱SAS一極の流れは感じます.しかし現状各企業のアンケートとかを見る限り,日本におけるOSTの浸透率はまだ極めて限定的ということも思い知らされたりしてます


SASのクソな部分をぶった切る!(2) SASユーザー総会

https://superman-jp.hatenablog.com/entry/SAS-disadvantage-2

>ぐさっときますねぇ….SAS社の情報発信の在り方とか,ユーザー総会の運営・サポートのやり方がベストではないというのは同感です

「発表者の実績になりにくい」これはどうかなぁ,N of 1じゃ 証拠にならないかもですが,私は結構転職してる人なのですが,給料交渉で,ユーザー総会の論文発表歴とかで結構上がることが多かったですね.

あと一回医薬でSASに浸かると,他業界(金融とかリサーチとか)にジャンプ転職が異常にしにくくなって書類で全部落ちるのですが,発表歴があると,なんかわりと通ります.それがあったから面接したって面接官が言ってたので効いたりもするのでしょう.自称SAS使い,自称データサイエンティストの怪しい人って巷に結構いるので差別化?区別してもらうのにはいいのかなとか.

あと,社内評価とかも,自己プレゼンのやり方によると思うのですが,「XXXを頑張って勉強する」とかより「XXXを研究した結果を総会で論文発表しました」ってほうがウケがちなのと,会社によるけど社内表彰とかでお小遣い稼ぎできたり.

でも結局,面白い人に会えるから,狂人の一歩手前の賢人とか,いい意味でヤバいプログラマの遭遇率が高いから毎年行ってるのが,私自身の動機かなと自己分析.SASのこと発表したり,知らない人,知ってる人とSASの話すると楽しいなぁとか.

結局,困った時に助けてくれる人とか,普段情報交換する信頼できる人とかが全部ユーザー総会で知り合った人だったりするんですよね.私は変だけど,プライベートも含めて友達が全部ユーザー総会由来だから,人間関係のために参加してるってことになるのかな…

でも,そういう仲良しこよしグループで内輪盛り上がりなムードがあって,それが高齢化と相まって,よろしくない風土をユーザー総会に醸しつつあるっていうのは凄くわかります

「ハッシュオブジェクトとか、業務で使うのでしょうか?」

まあ,一応,ここだけは…,多分その人の見てきた風景,経験してきた分野や企業の数によると思いますが,普通に使ってるところ多いですよ.キーが一意でない場合にErrorになったり,余計な変数の上書きを防ぎやすいとか

速度以外の理由で,標準化されている会社多いと思います

SASハッシュオブジェクトは使うべき?(https://superman-jp.hatenablog.com/entry/SAS-hash-object)

でも速度中心に論じられているのですが,個人的にはハッシュオブジェクトを使う理由として,「速度」はおまけと考えています.どちかというと構造化しやすい,多人数の開発で処理を共通化しやすい,キー・データの管理がしやすいのがメリットかなと.

なので,臨床だとSDTMやADaMの形って,ハッシュオブジェクトで一番,扱いやすい形で,はめ込みやすい感じなのですね.極端な例ですが,ADSLとかだとfind メソッドと checkメソッドで,1データステップで処理が簡素に終わることもありえます

あと,自己参照したり,普段だとデータステップって上から下にしかいかないので,前後の推移をみて分岐するとかがやりにくいのですがハッシュオブジェクトやハッシュ反復子だとそれに反することができるのでいいかなと.

ePROやウェアラブルデバイスを試験に使うことが増えてきたので,業界的に利用を見かける機会は増えたかなと思うのですが,まあ私のところにそういう情報や質問が選択的に集中してるからそう感じるだけなのかもですね


SASのクソな部分をぶった切る!(3)作図環境

https://superman-jp.hatenablog.com/entry/SAS-disadvantage-3

>これもわかります(笑) 私は肌にあうのでRやPythonよりSASグラフ好きで(ただしgplotは糞嫌い),GTLもSGPLOTでも描きます.SGPLOTのオプション増えたので,基本SGで済ますけど,GTLが全ての母であるのもわかるので,GTLも書くことありますし,全部GTLで書く人も嫌いではない

SASのクソな部分をぶった切る!(4)拡張性

https://superman-jp.hatenablog.com/entry/SAS-disadvantage-4

>そうですね,これもわかります

PDVについては,この方式は,これはこれで1つの在り方として正解だと思いますね.グローバルフォーラムでアメリカに行った時に,SASの開発周りの方々の話も多く聞きましたが,1obs inputしてoutputするシーケンシャルな処理を極限まで突き詰めたのが現状のSASで,それに適した形の概念としてPDVがあるので,そういう設計思想なんだなと.

必ずしも高速化処理に向かないとは思わないかな.文字値のレングスの持ち方が処理のボトルネックになるところは正直クソだと思いますけどね

しかしながら,良き悪きは別としてPDVは独特なので,視野を広くしておかないと,SASばっかりやったあとにSQLとか行列系言語やると,習得がしんどいんですよね

ある言語の理解を深めるために他言語を勉強するのは真理だとおもいます


SASのクソな部分をぶった切る!(5)proc DS2はいらない子

https://superman-jp.hatenablog.com/entry/SAS-disadvantage-5

まあ,私自身はそんなにかかないのですが,周りにユーザーがいて,他の業界にいた時も職場で使われていたので,少しだけコメント.

SDTMとかADaMとか,形の決まったプログラムをDS2で管理してパフォーマンスあげたり,金融やリサーチ業界での定型処理をうまくDS2にしてたりして,すごく効率的に回してる現場もあるので,まあ,導入メリットなし,無意味とまではいえないかなと

なんちゃってオブジェクト指向なので,他言語の開発者に短期間で,SAS書いてもらわなきゃいけない時によかったり,DS2の方が学習コスト低いから,みたいな例もあるみたいです


つらつら書いてみましたが,特に自分の正義を主張するつもりもなく

私自身は毎日面白おかしくSASで仕事したり遊んだりする日々ですが,久しぶりになにか書いてみたくなったので書いてみました


来年こそは…

今年は10記事はあげると言っておきながらこの有様。
しかもずっと最近記事が、Pythonに浮気の話って…。ほんとすみませんでした
せめて最新のエントリーはSASの話にしておきたい

SASやめちゃったんですかって心配されるので、一応自己フォロー、
今年はSAS Global Forum,SASユーザー総会,Pharma SUG JAPAN SDE,Phuse JAPAN SDE(12/10)など、過去にない濃密さでSASやってました
日本のすべてのSASやってる人間に刺激と娯楽をという思いは相変わらずです。単純に時間がなかっただけです。

今年のお気に入りは、FCMPの中でハッシュ入れちゃうことですね。whereステートメント内でメソッドが動くのが素敵。

data Q1;
do x=1 to 5;
 output;
end;
run;

data Q2;
do x=2,3;
 output;
end;
run;

proc fcmp
outlib=work.functions.common;
function check(x);
declare hash h1(dataset: "Q2");
rc=h1.definekey("x");
rc=h1.definedone();
rc=h1.check();
if rc eq 0 then return(1);
else return(0);
endsub;
quit;
options cmplib = work.functions;

data OUT1;
 set Q1;
 where check(x);
 run;

これでQ2に存在するデータのみ、Q1から読み込まれます。

あとdictionaryオブジェクトっていうのもあって、面白そうなのと、最新だとPythonオブジェクトとかもでました

来年こそは、色んな活動と、並行して、ブログも書けまくれるように、成長したいです



浮気の話 Python 3 エンジニア認定基礎試験とったりしました

色々やらなければ,ならないことがあって,てんてこまいなのに,Pythonに手を出したりしてます.

だって,SASの集まり行っても,Python,Pythonと耳にすることが多くて,褒めるにせよ貶すにせよ,まず自分がやってみないとなと.
どうせやるなら,基礎からやろうということで,SAS BASEにあたるような試験とかないかなぁと思って,探して受験したのが

Python 3 エンジニア認定基礎試験
https://www.pythonic-exam.com/exam/basic
→プログラム設計者ご本人のチュートリアル本が,出題範囲となっていて,まあそりゃあ,確かですけどって試験ですね.
この本にプラスして,コーディングしながら学べる基礎本を1冊買うのがおススメかなってかんじです

合格体験記を投稿すると,かわいいヘビのぬいぐるみが貰えるという面白い趣向があります(なくなり次第終了ですって)
https://www.pythonic-exam.com/archives/category/success-story

またいつか,ゆっくり書きたいなぁと思ってます