402 Views
March 31, 24
スライド概要
[第3回大阪sas勉強会] 森岡裕
SAS言語を中心として,解析業務担当者・プログラマなのコミュニティを活性化したいです
CLASSDATA集計の薦め 私,ゼロ埋めしないので 森岡 裕
お・こ・と・わ・り 本発表は,発表者個人の責任で,いかなるものも代表しません. 内容は発表者の偏見にまみれています. 一般的な見解ではなく, とにかく偏った美意識に基づくものだと予めご了承ください.
主旨 ダミーデータセットをマージして,ゼロ埋めすることは正しくない
使用するテストデータ →グループ別カテゴリー別に要約統計量と検査値が4超の割合を算出する data test; group=1;category=1;VAL=1;output; group=1;category=1;VAL=2;output; group=1;category=1;VAL=3;output; group=1;category=2;VAL=4;output; group=1;category=2;VAL=5;output; group=1;category=3;VAL=6;output; group=1;category=3;VAL=7;output; group=3;category=2;VAL=8;output; group=3;category=2;VAL=9;output; group=3;category=2;VAL=1;output; group=3;category=2;VAL=2;output; group=3;category=3;VAL=5;output; run; data test; set test; FN=VAL>4; run; グループ(group):1,2,3 カテゴリー(category):1,2,3
普通に書けば,以下のような感じですかね proc summary data=test nway; class group category; var VAL FN; output out=out1_1(drop=_TYPE_ _FREQ_) n= mean= std= lclm= uclm= min= median= run; max= sum= /autoname; data out1_2; length group category 8. N FN FPER MEAN CLM STD CLM MIN MEDIAN MAX $15.; set out1_1; N = cats(VAL_N); FN=cats(FN_SUM); FPER=put(round(divide(FN_SUM,VAL_N)*100,0.1),8.1 -L); MEAN = put(round(VAL_Mean,0.1),8.1 -L); if ^missing(VAL_StdDev) then STD = put(round(VAL_StdDev,0.01),8.2 -L); else STD="-"; if n(VAL_lclm,VAL_uclm)=2 then CLM=catx(" , ",put(round(VAL_lclm,0.1),8.1),put(round(VAL_uclm,0.1),8.1)); else CLM="-"; MIN=cats(VAL_Min); MEDIAN=put(VAL_MEDIAN,8.1 -L); MAX=cats(VAL_Max); keep group--MAX; run;
当然,元のデータに存在する水準でしか集計されない 一例のため,STDと平均の信頼区間は算出不能
データに存在しなくても,規定の水準で集計結果を表示したい
data dummy; do group=1 to 3; do category=1 to 3; output; end; end; run; data out2_1; merge dummy out1_2; by group category; run; よく見るのが,dummyで全水準を持ったレイアウ トデータセットを作って,それにマージする方法. あとは,内容に応じて0やハイフンを代入する
data out2_2; set out2_1; array zero N FN; do over zero; zero=coalescec(zero,"0"); end; array hy FPER--MAX; do over hy; hy=coalescec(hy,"-"); end; run;
気に食わない.私はこのやり方が気に食わない. 実際に集計していないのに,あとから欠損を0に変換して 体裁をごまかしているだけ. データがないならないで,その水準で集計して,きちんとn=0という結 果を得るべきである. 結果は同じでも,正しい道を歩むべきである
data clds; do group=1 to 3; do category=1 to 3; output; end; end; run; proc summary data=test classdata=clds nway; class group category; var VAL FN; output out=out3_1(drop=_TYPE_ _FREQ_) n= mean= std= lclm= uclm= min= median= run; max= sum= /autoname;
dummyを作ってマージするのと似たようなもんじゃないかと思うかもし れないけども. きちんと与えられた水準で集計することで,0とするべきものにはきち んと0が入り,算出不能なもののみが欠損となる →あとは全ての値について欠損をハイフンに変えるだけでよい. →余計な忖度が入らないので,ミスが起きない
data wk1; set adam.adae adam.adae(in=ina) end=eof; where saffl="Y"; where same anl01fl="Y"; if ina then trtan=4; AEの事象別集計のように水準が確定しないものについても応用ができる. 多群の試験において,いずれかの群にのみ生じた事象はその他の群では 度数0になるということなので,群を問わずに発生した事象をユニークに したデータセットを作成し,それを群で倍化重複してクラスデータに すればよい /*SOCクラスデータをhashで作成*/ if _N_=1 then do; declare hash soc(); soc.definekey("AEBDSYCD","AEBODSYS"); soc.definedone(); end; /*PTクラスデータをhashで作成*/ if _N_=1 then do; declare hash pt(); pt.definekey("AEPTCD","AEDECOD","AEBDSYCD"); pt.definedone(); end; soc.ref(); pt.ref(); if eof then do; soc.output(dataset:"_soc_class"); pt.output(dataset:"_pt_class"); end; run; data soc_class; set _soc_class; do TRTAN=1 to 4; output; end; run; data pt_class; set _pt_class; do TRTAN=1 to 4; output; end; run;
/*soc例数集計*/ proc sort data=wk1 out=_wk1 nodupkey; by USUBJID TRTAN AEBDSYCD AEBODSYS ; run; proc summary data=_wk1 classdata=soc_class nway exclusive ; class TRTAN AEBDSYCD AEBODSYS ; var TRTAN; output out=soc_1(drop=_TYPE_ _FREQ_) n=count ; run; /*soc件数集計*/ proc summary data=wk1 classdata=soc_class nway exclusive ; class TRTAN AEBDSYCD AEBODSYS ; var TRTAN; output out=esoc_1(drop=_TYPE_ _FREQ_) n=ecount ; run;
水準が動的な解析については,ハッシュオブジェクトで何か処置のつい でにクラスデータを作成しておき,それでsummaryするのが私の定跡 文句があるならかかってこい!!
ご清聴ありがとうございました