データセットはlong data typeとwide data typeに大別できます(いわゆる縦持ちと横持ちってやつです).
たいていの分析はwide data、すなわち一人につき一行で横に連なるデータを使って処理することが多いと思います.
しかし縦持ちデータを使えるようになるとデータ加工が各段にレベルアップします.そしてそれは決して難しくはありません.
今回は縦持ちデータセットの加工の仕方に関する代表的な4つの手法について、具体的な例を交えながら説明したいと思います.
1.最大値・最小値・平均値を取り出す
複数のレコードの最大値や最小値、平均値などの要約値を取り出すのに、byまたはbysortとegenコマンドを活用します.
このうちegenコマンドは非常に便利なのでここでいくつか付随する関数をご紹介します.
まず、egenの基本のsyntaxは、
.egen newvar = function(変数あるいは計算式), option
というものですが、function, つまり関数をいくつか知っておくと便利ということです.
① max, min, median, mean:そのものずばりの値を返します.これらの関数はうしろの括弧に変数あるいは計算式を入れられます.
② count:レコード数を返します.
③ total:ある値や計算式をすべて足し合わせます.
2.一番最初のレコードと比較して値を作り出す
eGFR 50%減少やCr 2倍化といったアウトカムを検出するのに前後の値と比較するのにシステム変数の1つである行番号の指定を使います.
これは変数名のすぐ後に、
変数名[行番号]
という形で操作するもので、条件付けなどを行うのに適しています.
これにbysortを組み合わせることで、例えば1人の対象者の反復測定値の変化に対して一定の規則を満たした場合にフラグを立てることができます.
bysort id: generate newvar = 変数名[1]
とすれば、対象者の一番初めのデータを新しい変数として置くことができます.
ただしこのとき、反復測定値の順番をあらかじめ整理しておくことが必要です.すなわち、visit番号や日付、あるいは昇順・降順にソートしておくことです.
もう少し複雑に、ベースラインの値から50%上昇するのが2回続いた最初のものをアウトカムにする、という場合は以下の様なやり方が考えられます.
sort id visit /* IDとvisit番号で並べ替え.IDが優先 */
bysort id: generate outcome = 1 if (var-var[1])/var[1] >= 50 & (var[_n+1]-var[1])/var[1] >= 50 & (var[_n-1]-var[1])/var[1] < 50 /* 1つ下の行のものはvar[_n+1], 1つ上のものはvar[_n-1] */
bysort id outcome visit: generate duplicate = _n /* 重複がないか確認. アウトカムに達成した順に1,2,3...と番号が付くので最初のものをアウトカムとするときはこれが1より大きいとき削除 */
replace outcome = . if duplicate > 1
drop duplicate
このときにきちんと一義的に決まるような並べ替えをしておくことが重要です.同じvisit番号で複数の測定をしているような状況もないわけではありませんので、あらかじめ重複の確認はしておいたほうがよいでしょう.
3.レコード数のカウント
上の項にもでてきましたが、順番に通し番号を振ることで一番大きな値をみればカウントになります.
あるいは、egenコマンドで、count関数を使えば測定回数を数えることができます.これで特定の期間でどのくらいの測定回数があるかを平均したりすることができます.
やり方は色々あるとは思いますが、例えば最初の半年間で3回以上は測定値があるものを対象に研究したい場合、
① 最初の3ヶ月以内というフラグを立てる.具体的にはIDごとにソートしたあと、visitごとに最初のvisitとの差分が90日以内であるフラグを立てる.
② ①で作ったフラグの立っている期間だけで対象者ごとの測定の回数をegenで求める.
③ 3回以上の測定がある対象者のみにフラグを立てる
sort id visit /* IDとvisit番号で並べ替え.IDが優先 */
bysort id: generate range90days = 1 if date-date[1] <= 90 /* 最初のvisitの日付との差分90日以内 */
bysort id: egen density90 = count(var) if range90days == 1
bysort id: gen elibility = 1 if density90[1] >=3
drop duplicate
4.反復データの回帰直線の傾きを得る
混合効果モデルあるいは一次回帰直線の傾きを得るのに縦のデータになっているほうが計算しやすいです.
線形回帰による傾きの場合は時間の変数を独立変数として計算をします.このとき、システム変数で傾きの部分を取り出すコマンドを用意しておけば対象者ごとの傾きを得ることができます.
sort id visit /* IDとvisit番号で並べ替え.IDが優先 */
bysort id: regress var visit /* visitごとの間隔でどのくらい変化するかがわかる.月1回のvisitならあとで12倍すれば年間変化によみかえられる */
bysort id: gen slope = _b[visit]*12
こんな具合です.
混合効果モデルであればbysortしなくてもよく、
.mixed var visit || id:visit
として、それぞれrandom effect, fix effectをとりだして計算します.これについてはまた改めて説明します.
5.まとめ
縦持ちのデータの具体的な活用シーンについてまとめました.システム変数やマクロを駆使するとさらに応用範囲を広げることができますので、ぜひいろいろチャレンジしましょう.
コメント