このブログでは、統計解析ソフトStataのプログラミングのTipsや便利コマンドを紹介しています.
Facebook groupでは、ちょっとした疑問や気づいたことなどを共有して貰うフォーラムになっています. ブログと合わせて個人の学習に役立てて貰えれば幸いです.
さて、本日の記事は、縦持ちのデータを加工するための方法を考えてみたので紹介したいと思います.ベストな方法ではないにしろ、一つのやり方と思っていただければと思います.
例えば院内のDPCデータを基準にして、その入院時情報からイベントを予測する研究をしたい場合を想定してみます.具体的なサンプルデータセットを使いながら解説を行ってみたいと思います.
1.データセットの概要
1人の患者さんが複数の入院を経験することはよくある話だと思いますが、話を単純にするため、1入院をanalysis unitとして、2回目以降の入院を別人扱いすることにします.
ここでは以下の2種類のデータセット “admission_data” と “labodata” というのを使って解説します.
“admission_data”は各患者ごとに複数の入院日と退院日を記録したデータセットになります.
これも賛否両論だとは思いますが、自分がやっていくなかでこれが一番シンプルでやりやすいと感じたのでこのように整えることにしました.
この整え方の良い点は、一患者一行となるためマージしやすい点にあります.縦持ちデータと結合する場合、m:mでのマージというのは絶対に避けた方がよいです.
これに対して、検査データは縦持ちです.すなわち、1人の患者が複数ポイントでの観測値を縦に連ねる形式になっています.
この縦持ちのデータに先ほどの入院日データの横持ちデータを結合させて入退院日の間にある検査所見、あるいは入院日から~日遡っての検査所見などの条件で、合致するもののみを拾ってくるという方法をとるわけです.
このデータセットを使ってデータを結合させる方法をご紹介します.
2.具体的なプログラムの一例
まずは縦持ちのデータを最初に展開します.そこにm:1で入退院横持ちデータを結合します.
use labodata, clear
merge m:1 strcase using admission_data /* 縦持ちの検査データに横持ちの入院情報を結合する */
keep if _merge==3
/* それぞれの情報ソースが合致しないものは除く */
drop _merge
次に、とりあえず新しい入退院の日付の変数を作成しておいて、該当する入退院日を結合した横持ちデータからとってきます.このときループコマンドを使うとスムーズです.今回は最大4入院だったのですが、それがもっとたくさん繰り返し入院している場合にはforvaluesのあとの因数を増やすだけです.
generate lab_admissiondt = . /* とりあえず新しい入院日を仮に作成 */
generate lab_dischargdt = . /* とりあえず新しい退院日を仮に作成 */
forvalues n = 1/4 {
replace lab_admissiondt = admissiondt`n' if inrange(labdate, admissiondt`n', dischargdt`n') & lab_admissiondt==. /* 複数ある入院日のどこに該当するかを順番に検討する */
replace lab_dischargdt = dischargdt`n' if inrange(labdate, admissiondt`n', dischargdt`n') & lab_dischargdt==.
}
最終的には入院日とその翌日のデータのみをベースライン値として採用することにしたとすると、いかのようなプログラムになりますね.ここの条件はもっとフレキシブルに変更することができます.
drop if lab_admissiondt==.
/* 合致しない場合は削除 */
drop admissiondt* dischargdt*
/* オリジナルの日付は削除 */
format lab_admissiondt lab_dischargdt %td
gen flag = inrange(labdate, lab_admissiondt, lab_admissiondt + 1), after(labdate)
/* 入院初日または翌日のデータを利用 */
keep if flag==1
rename lab_admissiondt admissiondt
/* 入退院の日付を表す変数に再び戻す */
rename lab_dischargdt dischargdt
最終的にこんな形でやってみるといいのではないでしょうか、という提案です.もっとよいやり方があると思います.
use labodata, clear
merge m:1 strcase using admission_data /* 縦持ちの検査データに横持ちの入院情報を結合する */
keep if _merge==3
/* それぞれの情報ソースが合致しないものは除く */
drop _merge
generate lab_admissiondt = . /* とりあえず新しい入院日を仮に作成 */
generate lab_dischargdt = . /* とりあえず新しい退院日を仮に作成 */
forvalues n = 1/4 {
replace lab_admissiondt = admissiondt`n' if inrange(labdate, admissiondt`n', dischargdt`n') & lab_admissiondt==. /* 複数ある入院日のどこに該当するかを順番に検討する */
replace lab_dischargdt = dischargdt`n' if inrange(labdate, admissiondt`n', dischargdt`n') & lab_dischargdt==.
}
drop if lab_admissiondt==.
/* 合致しない場合は削除 */
drop admissiondt* dischargdt*
/* オリジナルの日付は削除 */
format lab_admissiondt lab_dischargdt %td
gen flag = inrange(labdate, lab_admissiondt, lab_admissiondt + 1), after(labdate)
/* 入院初日または翌日のデータを利用 */
keep if flag==1
rename lab_admissiondt admissiondt
/* 入退院の日付を表す変数に再び戻す */
rename lab_dischargdt dischargdt
まとめ
データクリーニングのプロセスで自分で作ったプログラムをご紹介しました.これは正解が一つではなく、いかにしてシンプルな方法を生むことができるか、という一つのアイディアを示したにすぎません.もっといいやり方があればコメントいただけると助かります.
上記のアイディアをいろいろなことに応用してみるといろいろな発見があると思いますので、ぜひプログラムを組んでみてくださいね.
コメント