2017年2月28日火曜日

頻度集計で存在しない水準値を0件として出したい【PROC TABULATE編】




頻度集計で存在しない水準値を0件として出したい【PROC SUMMARY編】の続き。


PROC TABULATEでも0件の水準を出すことができます。
今回使用するサンプルデータは前回と一緒ですが、あらためて以下に載せておきます。

*** サンプルデータ作成 ;
data DT1;
input NO$ YN SEX;
cards;
001 1 2
002 1 2
;

YN…何かの有無(0=無、1=有)
SEX…性別(1=男、2=女)




*** FORMAT作成 ;
proc format;
   value _YN
   0 = "無"
   1 = "有"
   ;
   value _SEX
   1 = "男"
   2 = "女"
   ;
run;



以下がYNとSEXの頻度集計をPROC TABULATEで行う例です。
集計対象が0オブザベーションの場合、今回紹介するオプションは機能しません。
※その他、注意点についても記事の下の方で紹介しています。

proc tabulate data=DT1;
   class YN SEX         /  missing preloadfmt;
   table (YN SEX) , n  /  printmiss  misstext="0";
   format YN _YN. SEX _SEX.;
run;




  • preloadfmt」「printmiss」で変数に割り当てたフォーマットを使って、0件の水準も出力されるようにしてます。
  • 0件の場合の表示内容を「misstext=」で指定します。今回は「"0"」と表示するようにしてます。


ちなみにclassステートメントに「missing」をつけているのは以下データステップ100万回で解説されている落とし穴予防の為です。
means summaryプロシジャのclassステートメント指定変数の欠損値には気を付けてって話


もう1つ注意ですが、
0件の水準を出すようにした結果をSASデータセットに出力すると、、

ods output Table=OUT1;
proc tabulate data=DT1;
   class YN SEX       /  missing preloadfmt;
   table (YN SEX) , n /  printmiss misstext="0";
   format YN _YN. SEX _SEX.;
run;
ods output close;

proc print data=OUT1 noobs;
   var YN SEX N;
run;


misstextオプションが効いてないのか、0件の水準は出るけど、「0」と出ずに欠損値で出ます。
これはまぁしょうがないかーって感じです。

ただ頻度集計・クロス集計・要約統計量の計算など、応用範囲広いのでSUMMARYやFREQよりこっち使うほうがいい場合もあるので是非TABULATEプロシジャを取り入れてみましょう。


以上、
PROC TABULATEの結果はデータセットに出力できる。
でちょっと触れたTABULATEを使った便利な機能の紹介でした。


2017年2月23日木曜日

頻度集計で存在しない水準値を0件として出したい【PROC SUMMARY編】



まずは失敗例から。

失敗例
*** サンプルデータ作成 ;
data DT1;
input NO$ YN SEX;
cards;
001 1 2
002 1 2
;

YN…何かの有無(0=無、1=有)
SEX…性別(1=男、2=女)




*** FORMAT作成 ;
proc format;
   value _YN
   0 = "無"
   1 = "有"
   ;
   value _SEX
   1 = "男"
   2 = "女"
   ;
run;

*** 変数YN, SEXの頻度集計 ;
proc freq data=DT1;
   tables YN SEX;
   format YN _YN. SEX _SEX.;
run;




変数YNとSEXの頻度集計をしています。

その際、YNに以下フォーマットを当てています
「0=無」「1=有」

SEXには以下フォーマットを当てています
「1=男」「2=女」

結果を見てみると、「YN=0 (無)」と「SEX=1(男)」の度数が出てませんね。
これは集計対象のデータセットDT1に該当の値が存在しないからです。



PROC FREQでは現状0件の水準を出せないので、PROC SUMMARYで出してみましょう。
※今回の例は「1変数毎の頻度集計」のみに対応しています
※また、集計対象が0オブザベーションの場合、今回紹介するオプションは機能しません。

proc summary data=DT1 print completetypes;
   class YN SEX / preloadfmt missing;
   format YN _YN. SEX _SEX.;
   ways 1;
run;


POINT1

PROC MEANSでも似たようなことが出来るけど、PROC SUMMARYを使った理由。
それは、以下の記事を見ると理解しやすいと思います。


ちょっと解説すると、2つのプロシジャの違いのひとつが「VARステートメント」を省略した場合。
  • PROC MEANS: CLASSステートメント等、その他のステートメントに指定していない「すべての数値変数の要約統計量」が求められる
  • PROC SUMMARY:「オブザベーション数」のみ求められる

今回は頻度集計を求めたいだけなので、PROC SUMMARYが最適というわけです。
(ちなみにPROC SUMMARYでは「PRINT」オプションを指定しないと出力結果が表示されません)


POINT2

サンプルプログラムで指定している「COMPLETETYPES」「PRELOADFMT」「WAYS」については以下の記事を見て頂くと理解しやすいと思います。


ちなみにCLASSステートメントに「MISSING」をつけているのは以下データステップ100万回で解説されている落とし穴予防の為です(今回の例では問題ないけど)

2017年2月20日月曜日

SASデータセットをXPTファイルに変換する方法




SASデータセットをXPT(XPORT)という移送形式ファイルに変換する方法。



今回のサンプルデータ


MYSASというライブラリを作り、そこにデータセットADSLを格納しときます。

libname MYSAS "適当なパス";

data ADSL (label="SUBJECT LEVEL ANALYSIS DATASET");
   USUBJID="aaa";
run;

proc sort data=ADSL out=MYSAS.ADSL;
   by USUBJID;
run;





XPTファイルに変換するプログラム


以下プログラムを実行するとログにWARNINGが出るかもしれません。
「制限事項」のとこで補足説明してるので今は無視してください。

libname MYXPT xport "XPTファイルを格納するパス\adsl.xpt";

proc copy in=MYSAS out=MYXPT memtype=data;
   select ADSL;
run;

  • libnameでXPTファイルを格納するライブラリ参照を定義。ここではXPTファイル名を含むフルパスを指定する。
  •  proc copyでMYSAS.ADSLをライブラリMYXPTに格納。





制限事項


SASデータセットがSORTプロシジャでソートしてある場合、内部的にSORT情報が保持されており、この状態でXPT変換すると以下のようなWARNINGが表示されます。

proc sort data=MYSAS.ADSL;
   by USUBJID;
run;

libname MYXPT xport "XPTファイルを格納するパス\adsl.xpt";
proc copy in=MYSAS out=MYXPT memtype=data;
   select ADSL;
run;

ログ
WARNING: エンジンXPORTはSORTEDBY処理をサポートしていません。SORTEDBY情報はコピーできません。


ログに出てる通り、XPTではSORT情報が持たせられません。
WARNINGは出ているけどSORT情報がなくなっただけでXPTファイルはちゃんと出来ています。


このWARNINGが嫌であれば、この記事の最初のMYSAS.ADSLを作るプログラムのとこでSORTプロシジャにSORTEDBYオプションを追記すると、SORT情報を消すことができます。

proc sort data=ADSL out=MYSAS.ADSL (sortedby=_null_);
   by USUBJID;
run;

out=にこのオプションを指定するのがポイントです。



その他の制限。
  • 変数名は8文字以内
  • 変数ラベルの長さは40まで
  • データセットラベルも長さ40まで・・・など




製薬業界でのCDISC絡みの話。(2017/02/17現在での話)

CPORTプロシジャでも移送ファイル(CPTファイル)に変換できますが、
PMDAからでてる「技術的ガイドについて」という通知には「CPORT Procedureは使用しないこと」という記述があるのでご注意ください。



2017年2月16日木曜日

データセットオプションとは?



以下をご覧ください。

data DT1;
   set  SASHELP.CLASS (keep=NAME SEX AGE);
run;


データセット「SASHELP.CLASS」をSETする時に、変数「NAME SEX AGE」のみを保持しています。
このように ”データセット名 (オプション)” という形式で指定するオプションを、データセットオプションといいます。



特徴

・ データステップやプロシジャなどあらゆるところで、データセット名の横にこのオプションを指定できる。
・ オプションは指定された場所で作用する。


いくつか例を見てみましょう。

例1 ;
data DT1 (keep=NAME);
   set SASHELP.CLASS (keep=NAME SEX AGE);
run;

① SETする時に変数NAME、SEX、AGEだけKEEPさせてから、、
② 出力時に変数NAMEをKEEPしています。



例2 ;
proc means data=SASHELP.CLASS;
 var AGE;
 output out=DT2 (keep=_STAT_ AGE);
run;

① MEANSの結果をデータセットに出力する際、変数_STAT、AGEだけをKEEPしています。



よく使われるデータセットオプション(一部紹介)


KEEPだけでなく、色々なオプションがあります。
  内容  構文
 必要な変数だけ保持

 データセット名 ( KEEP=変数1  変数2 );
 不要な変数の削除

 データセット名 ( DROP=変数1  変数2 );

 変数名の変更

 データセット名 ( RENAME=(変数X=変数Y  変数Z=変数W) )
 抽出条件

 データセット名 ( WHERE=(抽出条件) )



data DT1;
   set SASHELP.CLASS (rename=(NAME=NAMAE) where=(AGE=13));
run;




注意

・オプションの実行順についての注意点。データステップ100万回にて分かり易く解説をされています。
データセットオプションの適応順の推測

・WHEREステートメントとWHERE=データセットオプションを併用する際の注意事項
・すべてのプロシジャでデータセットオプションに対応しているかは未検証です(というか、ほぼ検証不可。。)



その他役に立ちそうな関連記事

2017年2月14日火曜日

PROC REPORTで先頭の半角スペースを保持する方法(ODS出力時)



ちょっと前に以下の記事を書きました。
PROC REPORTでインデントをつける方法(ODS出力時)


そして昨日マニュアル読み漁ってたら違う方法みつけました。
ちなみに「ODS RTF」での例になります。その他の出力先でも今回の方法が使用できるかはリファレンスをご確認下さい。


以下のような、先頭に半角スペースが入っている変数があったとします。

* Sample data ;
data dt1;
length a $3.;
a="aaa";output;
a=" bb";output;
a="ccc";output;
a=" dd";output;
run;

aaa 
 bb  
ccc  
 dd 


そして以下、変数Aのデータ部分の先頭の半角スペースを保持する例
(注意事項があるので下の説明もご覧下さい)

ods rtf file="出力するRTFファイルのフルパス";
proc report data=dt1;
  define a / display  style(column) = {asis = on};
run;
ods rtf close;

styleオプションの「asis=on」で先頭の半角スペースを保持してくれます。
(注意: ちなみに変数値に改行が含まれてる場合、改行も保持するようになります)


また、全変数のデータ部分に対してこのオプションを適用したい場合は、以下のように書きます。

ods rtf file="出力するRTFファイルのフルパス";
proc report data=dt1 style(column) = {asis = on};
  define a / display;
run;
ods rtf close;


2017年2月10日金曜日

PROC TABULATEの結果はデータセットに出力できる。



集計にはFREQ、MEANSを使う事が多いですが、TABULATEプロシジャでも出来ます。
なおかつ集計結果をデータセットに出力できるので、使いこなせるとめちゃくちゃ便利です。


簡単な例

適当にPROC TABULATEを実行して結果をデータセットに出力する例

proc tabulate data=SASHELP.CLASS out=OUT1;
  class AGE SEX;
  table AGE,SEX*n;
run;

データセットOUT1


Tips)分類変数が欠損値のオブザベーションを集計に含めるには、MISSINGオプションを忘れずに!
欠損値の分類も集計に含めるMISSINGオプションと落とし穴